1*13044Ssam /* kern_descrip.c 5.25 83/06/12 */ 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" 15*13044Ssam #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); 8712748Ssam closef(u.u_ofile[uap->j], u.u_pofile[uap->j]); 887422Sroot if (u.u_error) 897422Sroot return; 907497Sroot /* u.u_ofile[uap->j] = 0; */ 917696Ssam /* u.u_pofile[uap->j] = 0; */ 927422Sroot } 9312748Ssam dupit(uap->j, fp, u.u_pofile[uap->i]); 947696Ssam } 957696Ssam 967696Ssam dupit(fd, fp, lockflags) 977696Ssam int fd; 987696Ssam register struct file *fp; 997696Ssam register int lockflags; 1007696Ssam { 1017696Ssam 1027696Ssam u.u_ofile[fd] = fp; 1037696Ssam u.u_pofile[fd] = lockflags; 1047497Sroot fp->f_count++; 10512748Ssam /* THIS DOESN'T BELONG HERE */ 1069590Ssam if (lockflags&UF_SHLOCK) 10712748Ssam ((struct inode *)fp->f_data)->i_shlockc++; 1089590Ssam if (lockflags&UF_EXLOCK) 10912748Ssam ((struct inode *)fp->f_data)->i_exlockc++; 11012748Ssam /* END DOESN'T BELONG */ 1117422Sroot } 1127422Sroot 11312748Ssam /* 11412748Ssam * The file control system call. 11512748Ssam */ 11612748Ssam fcntl() 1177497Sroot { 1187497Sroot register struct file *fp; 1197497Sroot register struct a { 12012748Ssam int fdes; 12112748Ssam int cmd; 12212748Ssam int arg; 12312748Ssam } *uap; 12412748Ssam register i; 12512748Ssam register char *pop; 1267497Sroot 12712748Ssam uap = (struct a *)u.u_ap; 12812748Ssam fp = getf(uap->fdes); 12912748Ssam if (fp == NULL) 1307497Sroot return; 13112748Ssam pop = &u.u_pofile[uap->fdes]; 13212748Ssam switch(uap->cmd) { 13312748Ssam case 0: 13412748Ssam i = uap->arg; 13512748Ssam if (i < 0 || i > NOFILE) { 13612748Ssam u.u_error = EINVAL; 13712748Ssam return; 13812748Ssam } 13912748Ssam if ((i = ufalloc(i)) < 0) 14012748Ssam return; 14112748Ssam dupit(i, fp, *pop); 14212748Ssam break; 1437497Sroot 14412748Ssam case 1: 14512748Ssam u.u_r.r_val1 = *pop & 1; 14612748Ssam break; 1477422Sroot 14812748Ssam case 2: 14912748Ssam *pop = (*pop &~ 1) | (uap->arg & 1); 15012748Ssam break; 1518145Sroot 15212748Ssam case 3: 15312748Ssam u.u_r.r_val1 = fp->f_flag+FOPEN; 15412748Ssam break; 1558145Sroot 15612748Ssam case 4: 15712748Ssam fp->f_flag &= FCNTLCANT; 15812748Ssam fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 15912748Ssam u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); 1609995Ssam if (u.u_error) 16112748Ssam break; 16212748Ssam u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 16312748Ssam if (u.u_error) 16412748Ssam (void) fset(fp, FNDELAY, 0); 16512748Ssam break; 1667422Sroot 16712748Ssam case 5: 16812748Ssam u.u_error = fsetown(fp, uap->arg); 16912748Ssam break; 1707422Sroot 17112748Ssam case 6: 17212748Ssam u.u_error = fgetown(fp, &u.u_r.r_val1); 1737422Sroot break; 1748115Sroot 17512748Ssam default: 17612748Ssam u.u_error = EINVAL; 1777422Sroot } 1787422Sroot } 1797422Sroot 18012748Ssam fset(fp, bit, value) 18112748Ssam struct file *fp; 18212748Ssam int bit, value; 1837422Sroot { 1847422Sroot 18512748Ssam if (value) 18612748Ssam fp->f_flag |= bit; 18712748Ssam else 18812748Ssam fp->f_flag &= ~bit; 18912748Ssam return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 19012748Ssam (caddr_t)&value)); 19112748Ssam } 1927422Sroot 19312748Ssam fgetown(fp, valuep) 19412748Ssam struct file *fp; 19512748Ssam int *valuep; 19612748Ssam { 19712748Ssam int error; 1988115Sroot 19912748Ssam switch (fp->f_type) { 2008115Sroot 20112748Ssam case DTYPE_SOCKET: 20212748Ssam *valuep = ((struct socket *)fp->f_data)->so_pgrp; 20312748Ssam return (0); 2047497Sroot 20512748Ssam default: 20612748Ssam error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 20712748Ssam *valuep = -*valuep; 20812748Ssam return (error); 2097422Sroot } 2107422Sroot } 2117422Sroot 21212748Ssam fsetown(fp, value) 21312748Ssam struct file *fp; 21412748Ssam int value; 2157422Sroot { 2167422Sroot 21712748Ssam if (fp->f_type == DTYPE_SOCKET) { 21812748Ssam ((struct socket *)fp->f_data)->so_pgrp = value; 21912748Ssam return (0); 22012748Ssam } 22112748Ssam if (value > 0) { 22212748Ssam struct proc *p = pfind(value); 22312748Ssam if (p == 0) 22412748Ssam return (EINVAL); 22512748Ssam value = p->p_pgrp; 22612748Ssam } else 22712748Ssam value = -value; 22812748Ssam return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 2297422Sroot } 2307422Sroot 23112748Ssam fioctl(fp, cmd, value) 23212748Ssam struct file *fp; 23312748Ssam int cmd; 23412748Ssam caddr_t value; 2357422Sroot { 2367422Sroot 23712748Ssam return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 2387422Sroot } 2397422Sroot 24012748Ssam close() 2418029Sroot { 24212748Ssam register struct a { 24312748Ssam int i; 24412748Ssam } *uap = (struct a *)u.u_ap; 24512748Ssam register struct file *fp; 246*13044Ssam register u_char *pf; 2478029Sroot 24812748Ssam fp = getf(uap->i); 24912748Ssam if (fp == 0) 25012748Ssam return; 251*13044Ssam pf = (u_char *)&u.u_pofile[uap->i]; 252*13044Ssam if (*pf & UF_MAPPED) 25312748Ssam munmapfd(uap->i); 254*13044Ssam if (*pf & (UF_SHLOCK|UF_EXLOCK)) 255*13044Ssam unlockf(fp, pf); 256*13044Ssam closef(fp); 25712748Ssam /* WHAT IF u.u_error ? */ 25812748Ssam u.u_ofile[uap->i] = NULL; 259*13044Ssam *pf = 0; 2608029Sroot } 2618029Sroot 262*13044Ssam fstat() 263*13044Ssam { 264*13044Ssam register struct file *fp; 265*13044Ssam register struct a { 266*13044Ssam int fdes; 267*13044Ssam struct stat *sb; 268*13044Ssam } *uap; 269*13044Ssam struct stat ub; 270*13044Ssam 271*13044Ssam uap = (struct a *)u.u_ap; 272*13044Ssam fp = getf(uap->fdes); 273*13044Ssam if (fp == 0) 274*13044Ssam return; 275*13044Ssam switch (fp->f_type) { 276*13044Ssam 277*13044Ssam case DTYPE_INODE: 278*13044Ssam u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 279*13044Ssam break; 280*13044Ssam 281*13044Ssam case DTYPE_SOCKET: 282*13044Ssam u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 283*13044Ssam break; 284*13044Ssam 285*13044Ssam default: 286*13044Ssam panic("fstat"); 287*13044Ssam /*NOTREACHED*/ 288*13044Ssam } 289*13044Ssam if (u.u_error == 0) 290*13044Ssam u.u_error = copyout(&ub, uap->sb, sizeof (ub)); 291*13044Ssam } 292*13044Ssam 2937422Sroot /* 2947497Sroot * Allocate a user file descriptor. 2957422Sroot */ 29612748Ssam ufalloc(i) 29712748Ssam register int i; 2987422Sroot { 2997497Sroot 30012748Ssam for (; i < NOFILE; i++) 3017497Sroot if (u.u_ofile[i] == NULL) { 3027497Sroot u.u_r.r_val1 = i; 3037497Sroot u.u_pofile[i] = 0; 3047497Sroot return (i); 3057497Sroot } 3067497Sroot u.u_error = EMFILE; 3077497Sroot return (-1); 3087497Sroot } 3097497Sroot 31012748Ssam ufavail() 31112748Ssam { 31212748Ssam register int i, avail = 0; 31312748Ssam 31412748Ssam for (i = 0; i < NOFILE; i++) 31512748Ssam if (u.u_ofile[i] == NULL) 31612748Ssam avail++; 31712748Ssam return (avail); 31812748Ssam } 31912748Ssam 3207497Sroot struct file *lastf; 3217497Sroot /* 3227497Sroot * Allocate a user file descriptor 3237497Sroot * and a file structure. 3247497Sroot * Initialize the descriptor 3257497Sroot * to point at the file structure. 3267497Sroot */ 3277497Sroot struct file * 3287497Sroot falloc() 3297497Sroot { 3307422Sroot register struct file *fp; 3317497Sroot register i; 3327422Sroot 33312748Ssam i = ufalloc(0); 3347497Sroot if (i < 0) 3357497Sroot return (NULL); 3367497Sroot if (lastf == 0) 3377497Sroot lastf = file; 3387497Sroot for (fp = lastf; fp < fileNFILE; fp++) 3397497Sroot if (fp->f_count == 0) 3407497Sroot goto slot; 3417497Sroot for (fp = file; fp < lastf; fp++) 3427497Sroot if (fp->f_count == 0) 3437497Sroot goto slot; 3447497Sroot tablefull("file"); 3457497Sroot u.u_error = ENFILE; 3467497Sroot return (NULL); 3477497Sroot slot: 3487497Sroot u.u_ofile[i] = fp; 34912748Ssam fp->f_count = 1; 35012748Ssam fp->f_data = 0; 3517497Sroot fp->f_offset = 0; 3527497Sroot lastf = fp + 1; 3537497Sroot return (fp); 3547497Sroot } 35512748Ssam 3567497Sroot /* 3577497Sroot * Convert a user supplied file descriptor into a pointer 3587497Sroot * to a file structure. Only task is to check range of the descriptor. 35912748Ssam * Critical paths should use the GETF macro. 3607497Sroot */ 3617497Sroot struct file * 3627497Sroot getf(f) 3637497Sroot register int f; 3647497Sroot { 3657497Sroot register struct file *fp; 3667497Sroot 3677497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 3687497Sroot u.u_error = EBADF; 3697497Sroot return (NULL); 3707497Sroot } 3717497Sroot return (fp); 3727497Sroot } 3737497Sroot 3747497Sroot /* 3757497Sroot * Internal form of close. 37612748Ssam * Decrement reference count on file structure. 37712748Ssam * If last reference not going away, but no more 37812748Ssam * references except in message queues, run a 37912748Ssam * garbage collect. This would better be done by 38012748Ssam * forcing a gc() to happen sometime soon, rather 38112748Ssam * than running one each time. 3827497Sroot */ 383*13044Ssam closef(fp) 3847497Sroot register struct file *fp; 3857497Sroot { 3867497Sroot 3877422Sroot if (fp == NULL) 3887422Sroot return; 3897497Sroot if (fp->f_count > 1) { 3907497Sroot fp->f_count--; 39112748Ssam if (fp->f_count == fp->f_msgcount) 39212748Ssam unp_gc(); 3937422Sroot return; 3947422Sroot } 395*13044Ssam (*fp->f_ops->fo_close)(fp); 3967497Sroot fp->f_count = 0; 3977422Sroot } 398*13044Ssam 399*13044Ssam /* 400*13044Ssam * Apply an advisory lock on a file descriptor. 401*13044Ssam */ 402*13044Ssam flock() 403*13044Ssam { 404*13044Ssam register struct a { 405*13044Ssam int fd; 406*13044Ssam int how; 407*13044Ssam } *uap = (struct a *)u.u_ap; 408*13044Ssam register struct file *fp; 409*13044Ssam register u_char *pf; 410*13044Ssam int cmd; 411*13044Ssam 412*13044Ssam fp = getf(uap->fd); 413*13044Ssam if (fp == NULL) 414*13044Ssam return; 415*13044Ssam cmd = uap->how; 416*13044Ssam pf = (u_char *)&u.u_pofile[uap->fd]; 417*13044Ssam if (cmd & LOCK_UN) { 418*13044Ssam unlockf(fp, pf); 419*13044Ssam return; 420*13044Ssam } 421*13044Ssam /* 422*13044Ssam * No reason to write lock a file we've already 423*13044Ssam * write locked, similarly with a read lock. 424*13044Ssam */ 425*13044Ssam if ((*pf & UF_EXLOCK) && (cmd & LOCK_EX) || 426*13044Ssam (*pf & UF_SHLOCK) && (cmd & LOCK_SH)) 427*13044Ssam return; 428*13044Ssam switch (fp->f_type) { 429*13044Ssam 430*13044Ssam case DTYPE_INODE: 431*13044Ssam u.u_error = ino_lock((struct inode *)fp->f_data, pf, cmd); 432*13044Ssam break; 433*13044Ssam 434*13044Ssam case DTYPE_SOCKET: 435*13044Ssam u.u_error = soo_lock((struct socket *)fp->f_data, pf, cmd); 436*13044Ssam break; 437*13044Ssam 438*13044Ssam default: 439*13044Ssam panic("lockf"); 440*13044Ssam } 441*13044Ssam } 442*13044Ssam 443*13044Ssam unlockf(fp, pf) 444*13044Ssam register struct file *fp; 445*13044Ssam register u_char *pf; 446*13044Ssam { 447*13044Ssam 448*13044Ssam if ((*pf & (UF_SHLOCK|UF_EXLOCK)) == 0) 449*13044Ssam return; 450*13044Ssam switch (fp->f_type) { 451*13044Ssam 452*13044Ssam case DTYPE_INODE: 453*13044Ssam ino_unlock((struct inode *)fp->f_data, *pf); 454*13044Ssam break; 455*13044Ssam 456*13044Ssam case DTYPE_SOCKET: 457*13044Ssam soo_unlock((struct socket *)fp->f_data, *pf); 458*13044Ssam break; 459*13044Ssam 460*13044Ssam default: 461*13044Ssam panic("unlockf"); 462*13044Ssam } 463*13044Ssam *pf &= ~(UF_SHLOCK|UF_EXLOCK); 464*13044Ssam } 465