1*8145Sroot /* kern_descrip.c 5.10 82/09/11 */ 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/inline.h" 137422Sroot #include "../h/socket.h" 147422Sroot #include "../h/socketvar.h" 157497Sroot #include "../h/mount.h" 167422Sroot 177497Sroot #include "../h/descrip.h" 187497Sroot 197422Sroot /* 207497Sroot * Descriptor management. 217422Sroot */ 227497Sroot 237497Sroot /* 247497Sroot * TODO: 257497Sroot * getf should be renamed 267497Sroot * ufalloc side effects are gross 277497Sroot */ 287497Sroot 297497Sroot /* 307497Sroot * System calls on descriptors. 317497Sroot */ 328029Sroot getdtablesize() 337497Sroot { 347497Sroot 357497Sroot u.u_r.r_val1 = NOFILE; 367497Sroot } 377497Sroot 388098Sroot getdprop() 398098Sroot { 408098Sroot register struct a { 418098Sroot int d; 428098Sroot struct dtype *dtypeb; 438098Sroot } *uap = (struct a *)u.u_ap; 448098Sroot register struct file *fp; 458098Sroot struct dtype adtype; 468098Sroot 478098Sroot fp = getf(uap->d); 488098Sroot if (fp == 0) 498098Sroot return; 508098Sroot adtype.dt_type = 0; /* XXX */ 518098Sroot adtype.dt_protocol = 0; /* XXX */ 528098Sroot if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 538098Sroot sizeof (struct dtype)) < 0) { 548098Sroot u.u_error = EFAULT; 558098Sroot return; 568098Sroot } 578098Sroot } 588098Sroot 598098Sroot getdopt() 608098Sroot { 618098Sroot 628098Sroot } 638098Sroot 648098Sroot setdopt() 658098Sroot { 668098Sroot 678098Sroot } 688098Sroot 697422Sroot dup() 707422Sroot { 717497Sroot register struct a { 727497Sroot int i; 737497Sroot } *uap = (struct a *) u.u_ap; 747696Ssam struct file *fp; 757696Ssam int j; 767497Sroot 777497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 787497Sroot 797497Sroot fp = getf(uap->i); 807497Sroot if (fp == 0) 817497Sroot return; 827497Sroot j = ufalloc(); 837497Sroot if (j < 0) 847497Sroot return; 857696Ssam dupit(j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 867497Sroot } 877497Sroot 887497Sroot dup2() 897497Sroot { 907422Sroot register struct a { 917497Sroot int i, j; 927497Sroot } *uap = (struct a *) u.u_ap; 937497Sroot register struct file *fp; 947422Sroot 957497Sroot fp = getf(uap->i); 967497Sroot if (fp == 0) 977422Sroot return; 987497Sroot if (uap->j < 0 || uap->j >= NOFILE) { 997497Sroot u.u_error = EBADF; 1007497Sroot return; 1017422Sroot } 1027497Sroot u.u_r.r_val1 = uap->j; 1037497Sroot if (uap->i == uap->j) 1047497Sroot return; 1057497Sroot if (u.u_ofile[uap->j]) { 1067696Ssam closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]); 1077422Sroot if (u.u_error) 1087422Sroot return; 1097497Sroot /* u.u_ofile[uap->j] = 0; */ 1107696Ssam /* u.u_pofile[uap->j] = 0; */ 1117422Sroot } 1127696Ssam dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 1137696Ssam } 1147696Ssam 1157696Ssam dupit(fd, fp, lockflags) 1167696Ssam int fd; 1177696Ssam register struct file *fp; 1187696Ssam register int lockflags; 1197696Ssam { 1207696Ssam 1217696Ssam u.u_ofile[fd] = fp; 1227696Ssam u.u_pofile[fd] = lockflags; 1237497Sroot fp->f_count++; 1247696Ssam if (lockflags&RDLOCK) 1257696Ssam fp->f_inode->i_rdlockc++; 1267696Ssam if (lockflags&WRLOCK) 1277696Ssam fp->f_inode->i_wrlockc++; 1287422Sroot } 1297422Sroot 1307497Sroot close() 1317497Sroot { 1327497Sroot register struct a { 1337497Sroot int i; 1347497Sroot } *uap = (struct a *)u.u_ap; 1357497Sroot register struct file *fp; 1367497Sroot 1377497Sroot fp = getf(uap->i); 1387497Sroot if (fp == 0) 1397497Sroot return; 1407696Ssam closef(fp, 0, u.u_pofile[uap->i]); 1417497Sroot /* WHAT IF u.u_error ? */ 1427696Ssam u.u_ofile[uap->i] = NULL; 1437696Ssam u.u_pofile[uap->i] = 0; 1447497Sroot } 1457497Sroot 1468029Sroot wrap() 1477497Sroot { 1487497Sroot register struct a { 1497497Sroot int d; 1507497Sroot struct dtype *dtypeb; 1517497Sroot } *uap = (struct a *)u.u_ap; 1527497Sroot register struct file *fp; 1537497Sroot struct dtype adtype; 1547497Sroot 1557497Sroot fp = getf(uap->d); 1567497Sroot if (fp == 0) 1577497Sroot return; 1587497Sroot if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 1597497Sroot sizeof (struct dtype)) < 0) { 1607497Sroot u.u_error = EFAULT; 1617497Sroot return; 1627497Sroot } 1637497Sroot /* DO WRAP */ 1647497Sroot } 1657497Sroot 1668115Sroot int unselect(); 1677422Sroot int nselcoll; 1687422Sroot /* 1697422Sroot * Select system call. 1707422Sroot */ 1718098Sroot select() 1727422Sroot { 1737422Sroot register struct uap { 174*8145Sroot int nd; 175*8145Sroot long *in; 176*8145Sroot long *ou; 177*8145Sroot long *ex; 1788029Sroot struct timeval *tv; 1798029Sroot } *uap = (struct uap *)u.u_ap; 1808115Sroot int ibits[3], obits[3]; 1818115Sroot struct timeval atv; 1827422Sroot int s, tsel, ncoll, rem; 1838115Sroot label_t lqsave; 1847422Sroot 185*8145Sroot if (uap->nd >= NOFILE) { 186*8145Sroot u.u_error = EINVAL; 187*8145Sroot return; 188*8145Sroot } 189*8145Sroot 190*8145Sroot #define getbits(name, x) \ 191*8145Sroot if (uap->name) { \ 192*8145Sroot if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 193*8145Sroot sizeof (ibits[x]))) { \ 194*8145Sroot u.u_error = EFAULT; \ 195*8145Sroot return; \ 196*8145Sroot } \ 197*8145Sroot } else \ 198*8145Sroot ibits[x] = 0; 199*8145Sroot getbits(in, 0); 200*8145Sroot getbits(ou, 1); 201*8145Sroot getbits(ex, 2); 202*8145Sroot #undef getbits 203*8145Sroot 2048029Sroot if (uap->tv) { 2058029Sroot if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 2068029Sroot u.u_error = EFAULT; 2078029Sroot return; 2088029Sroot } 2098115Sroot if (itimerfix(&atv)) { 2108115Sroot u.u_error = EINVAL; 2118115Sroot return; 2128115Sroot } 2138115Sroot s = spl7(); timevaladd(&atv, &time); splx(s); 2148115Sroot } 2157422Sroot retry: 2167422Sroot ncoll = nselcoll; 2177422Sroot u.u_procp->p_flag |= SSEL; 2188115Sroot u.u_r.r_val1 = selscan(ibits, obits); 2197422Sroot if (u.u_error) 2208115Sroot return; 2218115Sroot if (u.u_r.r_val1) 2227422Sroot goto done; 2238115Sroot s = spl6(); 224*8145Sroot if (uap->tv && timercmp(&time, &atv, >=)) { 2258115Sroot splx(s); 2267422Sroot goto done; 2278115Sroot } 2287422Sroot if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 2297422Sroot u.u_procp->p_flag &= ~SSEL; 2307422Sroot splx(s); 2317422Sroot goto retry; 2327422Sroot } 2337422Sroot u.u_procp->p_flag &= ~SSEL; 2348115Sroot if (uap->tv) { 2358115Sroot lqsave = u.u_qsave; 2368115Sroot if (setjmp(&u.u_qsave)) { 2378115Sroot untimeout(unselect, u.u_procp); 2388115Sroot u.u_error = EINTR; 2398115Sroot splx(s); 2408115Sroot return; 2418115Sroot } 2428115Sroot timeout(unselect, u.u_procp, hzto(&atv)); 2438115Sroot } 2448115Sroot sleep((caddr_t)&selwait, PZERO+1); 2458115Sroot if (uap->tv) { 2468115Sroot u.u_qsave = lqsave; 2478115Sroot untimeout(unselect, u.u_procp); 2488115Sroot } 2497422Sroot splx(s); 2508115Sroot goto retry; 2518115Sroot done: 252*8145Sroot #define putbits(name, x) \ 253*8145Sroot if (uap->name) { \ 254*8145Sroot if (copyout((caddr_t)obits[x], (caddr_t)uap->name, \ 255*8145Sroot sizeof (obits[x]))) { \ 256*8145Sroot u.u_error = EFAULT; \ 257*8145Sroot return; \ 258*8145Sroot } \ 2598115Sroot } 260*8145Sroot putbits(in, 0); 261*8145Sroot putbits(ou, 1); 262*8145Sroot putbits(ex, 2); 263*8145Sroot #undef putbits 2648115Sroot } 2657422Sroot 2668115Sroot unselect(p) 2678115Sroot register struct proc *p; 2688115Sroot { 2698115Sroot register int s = spl6(); 2707422Sroot 2718115Sroot switch (p->p_stat) { 2727422Sroot 2738115Sroot case SSLEEP: 2748115Sroot setrun(p); 2757422Sroot break; 2768115Sroot 2778115Sroot case SSTOP: 2788115Sroot unsleep(p); 2798115Sroot break; 2807422Sroot } 2818115Sroot splx(s); 2827422Sroot } 2837422Sroot 2848115Sroot selscan(ibits, obits) 2858115Sroot int *ibits, *obits; 2867422Sroot { 2878115Sroot register int which, bits, i; 2888115Sroot int flag; 2897422Sroot struct file *fp; 2908115Sroot int able; 2917422Sroot struct inode *ip; 2928115Sroot int n = 0; 2937422Sroot 2948115Sroot for (which = 0; which < 3; which++) { 2958115Sroot bits = ibits[which]; 2968115Sroot obits[which] = 0; 2978115Sroot switch (which) { 2987422Sroot 2998115Sroot case 0: 3008115Sroot flag = FREAD; break; 3018115Sroot 3028115Sroot case 1: 3038115Sroot flag = FWRITE; break; 3048115Sroot 3058115Sroot case 2: 3068115Sroot flag = 0; break; 3078115Sroot } 3088115Sroot while (i = ffs(bits)) { 3098115Sroot bits &= ~(1<<(i-1)); 3108115Sroot fp = u.u_ofile[i-1]; 3118115Sroot if (fp == NULL) { 3128115Sroot u.u_error = EBADF; 3137422Sroot break; 3147422Sroot } 3158115Sroot if (fp->f_type == DTYPE_SOCKET) 3168115Sroot able = soselect(fp->f_socket, flag); 3178115Sroot else { 3188115Sroot ip = fp->f_inode; 3198115Sroot switch (ip->i_mode & IFMT) { 3207497Sroot 3218115Sroot case IFCHR: 3228115Sroot able = 3238115Sroot (*cdevsw[major(ip->i_rdev)].d_select) 3248115Sroot (ip->i_rdev, flag); 3258115Sroot break; 3268115Sroot 3278115Sroot case IFBLK: 3288115Sroot case IFREG: 3298115Sroot case IFDIR: 3308115Sroot able = 1; 3318115Sroot break; 3328115Sroot } 3338115Sroot 3348115Sroot } 3358115Sroot if (able) { 3368115Sroot obits[which] |= (1<<(i-1)); 3378115Sroot n++; 3388115Sroot } 3397422Sroot } 3407422Sroot } 3418115Sroot return (n); 3427422Sroot } 3437422Sroot 3447422Sroot /*ARGSUSED*/ 3457422Sroot seltrue(dev, flag) 3467422Sroot dev_t dev; 3477422Sroot int flag; 3487422Sroot { 3497422Sroot 3507422Sroot return (1); 3517422Sroot } 3527422Sroot 3537422Sroot selwakeup(p, coll) 3547422Sroot register struct proc *p; 3557422Sroot int coll; 3567422Sroot { 3577422Sroot int s; 3587422Sroot 3597422Sroot if (coll) { 3607422Sroot nselcoll++; 3617422Sroot wakeup((caddr_t)&selwait); 3627422Sroot } 3637422Sroot if (p) { 3647422Sroot if (p->p_wchan == (caddr_t)&selwait) 3657422Sroot setrun(p); 3667422Sroot else { 3677422Sroot s = spl6(); 3687422Sroot if (p->p_flag & SSEL) 3697422Sroot p->p_flag &= ~SSEL; 3707422Sroot splx(s); 3717422Sroot } 3727422Sroot } 3737422Sroot } 3747422Sroot 3758029Sroot revoke() 3768029Sroot { 3778029Sroot 3788029Sroot /* XXX */ 3798029Sroot } 3808029Sroot 3817422Sroot /* 3827497Sroot * Allocate a user file descriptor. 3837422Sroot */ 3847497Sroot ufalloc() 3857422Sroot { 3867497Sroot register i; 3877497Sroot 3887497Sroot for (i=0; i<NOFILE; i++) 3897497Sroot if (u.u_ofile[i] == NULL) { 3907497Sroot u.u_r.r_val1 = i; 3917497Sroot u.u_pofile[i] = 0; 3927497Sroot return (i); 3937497Sroot } 3947497Sroot u.u_error = EMFILE; 3957497Sroot return (-1); 3967497Sroot } 3977497Sroot 3987497Sroot struct file *lastf; 3997497Sroot /* 4007497Sroot * Allocate a user file descriptor 4017497Sroot * and a file structure. 4027497Sroot * Initialize the descriptor 4037497Sroot * to point at the file structure. 4047497Sroot */ 4057497Sroot struct file * 4067497Sroot falloc() 4077497Sroot { 4087422Sroot register struct file *fp; 4097497Sroot register i; 4107422Sroot 4117497Sroot i = ufalloc(); 4127497Sroot if (i < 0) 4137497Sroot return (NULL); 4147497Sroot if (lastf == 0) 4157497Sroot lastf = file; 4167497Sroot for (fp = lastf; fp < fileNFILE; fp++) 4177497Sroot if (fp->f_count == 0) 4187497Sroot goto slot; 4197497Sroot for (fp = file; fp < lastf; fp++) 4207497Sroot if (fp->f_count == 0) 4217497Sroot goto slot; 4227497Sroot tablefull("file"); 4237497Sroot u.u_error = ENFILE; 4247497Sroot return (NULL); 4257497Sroot slot: 4267497Sroot u.u_ofile[i] = fp; 4277497Sroot fp->f_count++; 4287497Sroot fp->f_offset = 0; 4297497Sroot fp->f_inode = 0; 4307497Sroot lastf = fp + 1; 4317497Sroot return (fp); 4327497Sroot } 4337497Sroot /* 4347497Sroot * Convert a user supplied file descriptor into a pointer 4357497Sroot * to a file structure. Only task is to check range of the descriptor. 4367497Sroot * Critical paths should use the GETF macro, defined in inline.h. 4377497Sroot */ 4387497Sroot struct file * 4397497Sroot getf(f) 4407497Sroot register int f; 4417497Sroot { 4427497Sroot register struct file *fp; 4437497Sroot 4447497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 4457497Sroot u.u_error = EBADF; 4467497Sroot return (NULL); 4477497Sroot } 4487497Sroot return (fp); 4497497Sroot } 4507497Sroot 4517497Sroot /* 4527497Sroot * Internal form of close. 4537497Sroot * Decrement reference count on 4547497Sroot * file structure. 4557497Sroot * Also make sure the pipe protocol 4567497Sroot * does not constipate. 4577497Sroot * 4587497Sroot * Decrement reference count on the inode following 4597497Sroot * removal to the referencing file structure. 4607497Sroot * Call device handler on last close. 4617497Sroot * Nouser indicates that the user isn't available to present 4627497Sroot * errors to. 4637696Ssam * 4647696Ssam * Handling locking at this level is RIDICULOUS. 4657497Sroot */ 4667696Ssam closef(fp, nouser, flags) 4677497Sroot register struct file *fp; 4687696Ssam int nouser, flags; 4697497Sroot { 4707497Sroot register struct inode *ip; 4717497Sroot register struct mount *mp; 4727497Sroot int flag, mode; 4737497Sroot dev_t dev; 4747497Sroot register int (*cfunc)(); 4757497Sroot 4767422Sroot if (fp == NULL) 4777422Sroot return; 4787497Sroot if (fp->f_count > 1) { 4797497Sroot fp->f_count--; 4807422Sroot return; 4817422Sroot } 4827497Sroot if (fp->f_type == DTYPE_SOCKET) { 4837497Sroot u.u_error = 0; /* XXX */ 4847497Sroot soclose(fp->f_socket, nouser); 4857497Sroot if (nouser == 0 && u.u_error) 4867497Sroot return; 4877497Sroot fp->f_socket = 0; 4887497Sroot fp->f_count = 0; 4897497Sroot return; 4907497Sroot } 4917497Sroot flag = fp->f_flag; 4927497Sroot ip = fp->f_inode; 4937497Sroot dev = (dev_t)ip->i_rdev; 4947497Sroot mode = ip->i_mode & IFMT; 4957696Ssam flags &= RDLOCK|WRLOCK; /* conservative */ 4967696Ssam if (flags) 4977696Ssam funlocki(ip, flags); 4987497Sroot ilock(ip); 4997497Sroot iput(ip); 5007497Sroot fp->f_count = 0; 5017497Sroot 5027497Sroot switch (mode) { 5037497Sroot 5047497Sroot case IFCHR: 5057497Sroot cfunc = cdevsw[major(dev)].d_close; 5067497Sroot break; 5077497Sroot 5087497Sroot case IFBLK: 5097497Sroot /* 5107497Sroot * We don't want to really close the device if it is mounted 5117497Sroot */ 5127497Sroot for (mp = mount; mp < &mount[NMOUNT]; mp++) 5137497Sroot if (mp->m_bufp != NULL && mp->m_dev == dev) 5147497Sroot return; 5157497Sroot cfunc = bdevsw[major(dev)].d_close; 5167497Sroot break; 5177497Sroot 5187497Sroot default: 5197497Sroot return; 5207497Sroot } 5217497Sroot for (fp = file; fp < fileNFILE; fp++) { 5227497Sroot if (fp->f_type == DTYPE_SOCKET) /* XXX */ 5237497Sroot continue; 5247497Sroot if (fp->f_count && (ip = fp->f_inode) && 5257497Sroot ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 5267497Sroot return; 5277497Sroot } 5287497Sroot if (mode == IFBLK) { 5297497Sroot /* 5307497Sroot * On last close of a block device (that isn't mounted) 5317497Sroot * we must invalidate any in core blocks 5327497Sroot */ 5337497Sroot bflush(dev); 5347497Sroot binval(dev); 5357497Sroot } 5367497Sroot (*cfunc)(dev, flag, fp); 5377422Sroot } 5388119Sroot 5398119Sroot opause() 5408119Sroot { 5418119Sroot 5428119Sroot for (;;) 5438119Sroot sleep((caddr_t)&u, PSLEP); 5448119Sroot } 545