1*13101Ssam /* kern_descrip.c 5.26 83/06/14 */ 27422Sroot 37422Sroot #include "../h/param.h" 47422Sroot #include "../h/systm.h" 57422Sroot #include "../h/dir.h" 67422Sroot #include "../h/user.h" 78029Sroot #include "../h/kernel.h" 87422Sroot #include "../h/inode.h" 97422Sroot #include "../h/proc.h" 107422Sroot #include "../h/conf.h" 117422Sroot #include "../h/file.h" 127422Sroot #include "../h/socket.h" 137422Sroot #include "../h/socketvar.h" 147497Sroot #include "../h/mount.h" 1513044Ssam #include "../h/stat.h" 167422Sroot 1712748Ssam #include "../h/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 587497Sroot fp = getf(uap->i); 597497Sroot if (fp == 0) 607497Sroot return; 6112748Ssam j = ufalloc(0); 627497Sroot if (j < 0) 637497Sroot return; 6412748Ssam dupit(j, fp, u.u_pofile[uap->i]); 657497Sroot } 667497Sroot 677497Sroot dup2() 687497Sroot { 697422Sroot register struct a { 707497Sroot int i, j; 717497Sroot } *uap = (struct a *) u.u_ap; 727497Sroot register struct file *fp; 737422Sroot 747497Sroot fp = getf(uap->i); 757497Sroot if (fp == 0) 767422Sroot return; 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); 87*13101Ssam closef(u.u_ofile[uap->j]); 887422Sroot if (u.u_error) 897422Sroot return; 907422Sroot } 9112748Ssam dupit(uap->j, fp, u.u_pofile[uap->i]); 927696Ssam } 937696Ssam 94*13101Ssam dupit(fd, fp, flags) 957696Ssam int fd; 967696Ssam register struct file *fp; 97*13101Ssam register int flags; 987696Ssam { 997696Ssam 1007696Ssam u.u_ofile[fd] = fp; 101*13101Ssam u.u_pofile[fd] = flags; 1027497Sroot fp->f_count++; 1037422Sroot } 1047422Sroot 10512748Ssam /* 10612748Ssam * The file control system call. 10712748Ssam */ 10812748Ssam fcntl() 1097497Sroot { 1107497Sroot register struct file *fp; 1117497Sroot register struct a { 11212748Ssam int fdes; 11312748Ssam int cmd; 11412748Ssam int arg; 11512748Ssam } *uap; 11612748Ssam register i; 11712748Ssam register char *pop; 1187497Sroot 11912748Ssam uap = (struct a *)u.u_ap; 12012748Ssam fp = getf(uap->fdes); 12112748Ssam if (fp == NULL) 1227497Sroot return; 12312748Ssam pop = &u.u_pofile[uap->fdes]; 12412748Ssam switch(uap->cmd) { 12512748Ssam case 0: 12612748Ssam i = uap->arg; 12712748Ssam if (i < 0 || i > NOFILE) { 12812748Ssam u.u_error = EINVAL; 12912748Ssam return; 13012748Ssam } 13112748Ssam if ((i = ufalloc(i)) < 0) 13212748Ssam return; 13312748Ssam dupit(i, fp, *pop); 13412748Ssam break; 1357497Sroot 13612748Ssam case 1: 13712748Ssam u.u_r.r_val1 = *pop & 1; 13812748Ssam break; 1397422Sroot 14012748Ssam case 2: 14112748Ssam *pop = (*pop &~ 1) | (uap->arg & 1); 14212748Ssam break; 1438145Sroot 14412748Ssam case 3: 14512748Ssam u.u_r.r_val1 = fp->f_flag+FOPEN; 14612748Ssam break; 1478145Sroot 14812748Ssam case 4: 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 15912748Ssam case 5: 16012748Ssam u.u_error = fsetown(fp, uap->arg); 16112748Ssam break; 1627422Sroot 16312748Ssam case 6: 16412748Ssam u.u_error = fgetown(fp, &u.u_r.r_val1); 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 { 23412748Ssam register struct a { 23512748Ssam int i; 23612748Ssam } *uap = (struct a *)u.u_ap; 23712748Ssam register struct file *fp; 23813044Ssam register u_char *pf; 2398029Sroot 24012748Ssam fp = getf(uap->i); 24112748Ssam if (fp == 0) 24212748Ssam return; 24313044Ssam pf = (u_char *)&u.u_pofile[uap->i]; 24413044Ssam if (*pf & UF_MAPPED) 24512748Ssam munmapfd(uap->i); 24613044Ssam closef(fp); 24712748Ssam /* WHAT IF u.u_error ? */ 24812748Ssam u.u_ofile[uap->i] = NULL; 24913044Ssam *pf = 0; 2508029Sroot } 2518029Sroot 25213044Ssam fstat() 25313044Ssam { 25413044Ssam register struct file *fp; 25513044Ssam register struct a { 25613044Ssam int fdes; 25713044Ssam struct stat *sb; 25813044Ssam } *uap; 25913044Ssam struct stat ub; 26013044Ssam 26113044Ssam uap = (struct a *)u.u_ap; 26213044Ssam fp = getf(uap->fdes); 26313044Ssam if (fp == 0) 26413044Ssam return; 26513044Ssam switch (fp->f_type) { 26613044Ssam 26713044Ssam case DTYPE_INODE: 26813044Ssam u.u_error = ino_stat((struct inode *)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) 280*13101Ssam u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 281*13101Ssam sizeof (ub)); 28213044Ssam } 28313044Ssam 2847422Sroot /* 2857497Sroot * Allocate a user file descriptor. 2867422Sroot */ 28712748Ssam ufalloc(i) 28812748Ssam register int i; 2897422Sroot { 2907497Sroot 29112748Ssam for (; i < NOFILE; i++) 2927497Sroot if (u.u_ofile[i] == NULL) { 2937497Sroot u.u_r.r_val1 = i; 2947497Sroot u.u_pofile[i] = 0; 2957497Sroot return (i); 2967497Sroot } 2977497Sroot u.u_error = EMFILE; 2987497Sroot return (-1); 2997497Sroot } 3007497Sroot 30112748Ssam ufavail() 30212748Ssam { 30312748Ssam register int i, avail = 0; 30412748Ssam 30512748Ssam for (i = 0; i < NOFILE; i++) 30612748Ssam if (u.u_ofile[i] == NULL) 30712748Ssam avail++; 30812748Ssam return (avail); 30912748Ssam } 31012748Ssam 3117497Sroot struct file *lastf; 3127497Sroot /* 3137497Sroot * Allocate a user file descriptor 3147497Sroot * and a file structure. 3157497Sroot * Initialize the descriptor 3167497Sroot * to point at the file structure. 3177497Sroot */ 3187497Sroot struct file * 3197497Sroot falloc() 3207497Sroot { 3217422Sroot register struct file *fp; 3227497Sroot register i; 3237422Sroot 32412748Ssam i = ufalloc(0); 3257497Sroot if (i < 0) 3267497Sroot return (NULL); 3277497Sroot if (lastf == 0) 3287497Sroot lastf = file; 3297497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3307497Sroot if (fp->f_count == 0) 3317497Sroot goto slot; 3327497Sroot for (fp = file; fp < lastf; fp++) 3337497Sroot if (fp->f_count == 0) 3347497Sroot goto slot; 3357497Sroot tablefull("file"); 3367497Sroot u.u_error = ENFILE; 3377497Sroot return (NULL); 3387497Sroot slot: 3397497Sroot u.u_ofile[i] = fp; 34012748Ssam fp->f_count = 1; 34112748Ssam fp->f_data = 0; 3427497Sroot fp->f_offset = 0; 3437497Sroot lastf = fp + 1; 3447497Sroot return (fp); 3457497Sroot } 34612748Ssam 3477497Sroot /* 3487497Sroot * Convert a user supplied file descriptor into a pointer 3497497Sroot * to a file structure. Only task is to check range of the descriptor. 35012748Ssam * Critical paths should use the GETF macro. 3517497Sroot */ 3527497Sroot struct file * 3537497Sroot getf(f) 3547497Sroot register int f; 3557497Sroot { 3567497Sroot register struct file *fp; 3577497Sroot 3587497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 3597497Sroot u.u_error = EBADF; 3607497Sroot return (NULL); 3617497Sroot } 3627497Sroot return (fp); 3637497Sroot } 3647497Sroot 3657497Sroot /* 3667497Sroot * Internal form of close. 36712748Ssam * Decrement reference count on file structure. 36812748Ssam * If last reference not going away, but no more 36912748Ssam * references except in message queues, run a 37012748Ssam * garbage collect. This would better be done by 37112748Ssam * forcing a gc() to happen sometime soon, rather 37212748Ssam * than running one each time. 3737497Sroot */ 37413044Ssam closef(fp) 3757497Sroot register struct file *fp; 3767497Sroot { 3777497Sroot 3787422Sroot if (fp == NULL) 3797422Sroot return; 3807497Sroot if (fp->f_count > 1) { 3817497Sroot fp->f_count--; 38212748Ssam if (fp->f_count == fp->f_msgcount) 38312748Ssam unp_gc(); 3847422Sroot return; 3857422Sroot } 38613044Ssam (*fp->f_ops->fo_close)(fp); 3877497Sroot fp->f_count = 0; 3887422Sroot } 38913044Ssam 39013044Ssam /* 39113044Ssam * Apply an advisory lock on a file descriptor. 39213044Ssam */ 39313044Ssam flock() 39413044Ssam { 39513044Ssam register struct a { 39613044Ssam int fd; 39713044Ssam int how; 39813044Ssam } *uap = (struct a *)u.u_ap; 39913044Ssam register struct file *fp; 40013044Ssam 40113044Ssam fp = getf(uap->fd); 40213044Ssam if (fp == NULL) 40313044Ssam return; 404*13101Ssam if (fp->f_type != DTYPE_INODE) { 405*13101Ssam u.u_error = EOPNOTSUPP; 40613044Ssam return; 40713044Ssam } 408*13101Ssam if (uap->how & LOCK_UN) { 409*13101Ssam ino_unlock(fp, FSHLOCK|FEXLOCK); 41013044Ssam return; 41113044Ssam } 412*13101Ssam /* avoid work... */ 413*13101Ssam if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 414*13101Ssam (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 41513044Ssam return; 416*13101Ssam u.u_error = ino_lock(fp, uap->how); 41713044Ssam } 418