1*8622Sroot /* kern_descrip.c 5.13 82/10/17 */ 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" 157422Sroot 167497Sroot #include "../h/descrip.h" 177497Sroot 187422Sroot /* 197497Sroot * Descriptor management. 207422Sroot */ 217497Sroot 227497Sroot /* 237497Sroot * TODO: 247497Sroot * getf should be renamed 257497Sroot * ufalloc side effects are gross 267497Sroot */ 277497Sroot 287497Sroot /* 297497Sroot * System calls on descriptors. 307497Sroot */ 318029Sroot getdtablesize() 327497Sroot { 337497Sroot 347497Sroot u.u_r.r_val1 = NOFILE; 357497Sroot } 367497Sroot 378098Sroot getdprop() 388098Sroot { 398098Sroot register struct a { 408098Sroot int d; 418098Sroot struct dtype *dtypeb; 428098Sroot } *uap = (struct a *)u.u_ap; 438098Sroot register struct file *fp; 448098Sroot struct dtype adtype; 458098Sroot 468098Sroot fp = getf(uap->d); 478098Sroot if (fp == 0) 488098Sroot return; 498098Sroot adtype.dt_type = 0; /* XXX */ 508098Sroot adtype.dt_protocol = 0; /* XXX */ 518098Sroot if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 528098Sroot sizeof (struct dtype)) < 0) { 538098Sroot u.u_error = EFAULT; 548098Sroot return; 558098Sroot } 568098Sroot } 578098Sroot 588098Sroot getdopt() 598098Sroot { 608098Sroot 618098Sroot } 628098Sroot 638098Sroot setdopt() 648098Sroot { 658098Sroot 668098Sroot } 678098Sroot 687422Sroot dup() 697422Sroot { 707497Sroot register struct a { 717497Sroot int i; 727497Sroot } *uap = (struct a *) u.u_ap; 737696Ssam struct file *fp; 747696Ssam int j; 757497Sroot 767497Sroot if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 777497Sroot 787497Sroot fp = getf(uap->i); 797497Sroot if (fp == 0) 807497Sroot return; 817497Sroot j = ufalloc(); 827497Sroot if (j < 0) 837497Sroot return; 847696Ssam dupit(j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 857497Sroot } 867497Sroot 877497Sroot dup2() 887497Sroot { 897422Sroot register struct a { 907497Sroot int i, j; 917497Sroot } *uap = (struct a *) u.u_ap; 927497Sroot register struct file *fp; 937422Sroot 947497Sroot fp = getf(uap->i); 957497Sroot if (fp == 0) 967422Sroot return; 977497Sroot if (uap->j < 0 || uap->j >= NOFILE) { 987497Sroot u.u_error = EBADF; 997497Sroot return; 1007422Sroot } 1017497Sroot u.u_r.r_val1 = uap->j; 1027497Sroot if (uap->i == uap->j) 1037497Sroot return; 1047497Sroot if (u.u_ofile[uap->j]) { 1057696Ssam closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]); 1067422Sroot if (u.u_error) 1077422Sroot return; 1087497Sroot /* u.u_ofile[uap->j] = 0; */ 1097696Ssam /* u.u_pofile[uap->j] = 0; */ 1107422Sroot } 1117696Ssam dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 1127696Ssam } 1137696Ssam 1147696Ssam dupit(fd, fp, lockflags) 1157696Ssam int fd; 1167696Ssam register struct file *fp; 1177696Ssam register int lockflags; 1187696Ssam { 1197696Ssam 1207696Ssam u.u_ofile[fd] = fp; 1217696Ssam u.u_pofile[fd] = lockflags; 1227497Sroot fp->f_count++; 1237696Ssam if (lockflags&RDLOCK) 1247696Ssam fp->f_inode->i_rdlockc++; 1257696Ssam if (lockflags&WRLOCK) 1267696Ssam fp->f_inode->i_wrlockc++; 1277422Sroot } 1287422Sroot 1297497Sroot close() 1307497Sroot { 1317497Sroot register struct a { 1327497Sroot int i; 1337497Sroot } *uap = (struct a *)u.u_ap; 1347497Sroot register struct file *fp; 1357497Sroot 1367497Sroot fp = getf(uap->i); 1377497Sroot if (fp == 0) 1387497Sroot return; 1397696Ssam closef(fp, 0, u.u_pofile[uap->i]); 1407497Sroot /* WHAT IF u.u_error ? */ 1417696Ssam u.u_ofile[uap->i] = NULL; 1427696Ssam u.u_pofile[uap->i] = 0; 1437497Sroot } 1447497Sroot 1458029Sroot wrap() 1467497Sroot { 1477497Sroot register struct a { 1487497Sroot int d; 1497497Sroot struct dtype *dtypeb; 1507497Sroot } *uap = (struct a *)u.u_ap; 1517497Sroot register struct file *fp; 1527497Sroot struct dtype adtype; 1537497Sroot 1547497Sroot fp = getf(uap->d); 1557497Sroot if (fp == 0) 1567497Sroot return; 1577497Sroot if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 1587497Sroot sizeof (struct dtype)) < 0) { 1597497Sroot u.u_error = EFAULT; 1607497Sroot return; 1617497Sroot } 1627497Sroot /* DO WRAP */ 1637497Sroot } 1647497Sroot 1658115Sroot int unselect(); 1667422Sroot int nselcoll; 1677422Sroot /* 1687422Sroot * Select system call. 1697422Sroot */ 1708098Sroot select() 1717422Sroot { 1727422Sroot register struct uap { 1738145Sroot int nd; 1748145Sroot long *in; 1758145Sroot long *ou; 1768145Sroot long *ex; 1778029Sroot struct timeval *tv; 1788029Sroot } *uap = (struct uap *)u.u_ap; 1798115Sroot int ibits[3], obits[3]; 1808115Sroot struct timeval atv; 1818586Sroot int s, ncoll; 1828115Sroot label_t lqsave; 1837422Sroot 1848145Sroot if (uap->nd >= NOFILE) { 1858145Sroot u.u_error = EINVAL; 1868145Sroot return; 1878145Sroot } 1888145Sroot 1898145Sroot #define getbits(name, x) \ 1908145Sroot if (uap->name) { \ 1918145Sroot if (copyin((caddr_t)uap->name, (caddr_t)&ibits[x], \ 1928145Sroot sizeof (ibits[x]))) { \ 1938145Sroot u.u_error = EFAULT; \ 1948145Sroot return; \ 1958145Sroot } \ 1968145Sroot } else \ 1978145Sroot ibits[x] = 0; 1988145Sroot getbits(in, 0); 1998145Sroot getbits(ou, 1); 2008145Sroot getbits(ex, 2); 2018145Sroot #undef getbits 2028145Sroot 2038029Sroot if (uap->tv) { 2048029Sroot if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 2058029Sroot u.u_error = EFAULT; 2068029Sroot return; 2078029Sroot } 2088115Sroot if (itimerfix(&atv)) { 2098115Sroot u.u_error = EINVAL; 2108115Sroot return; 2118115Sroot } 2128115Sroot s = spl7(); timevaladd(&atv, &time); splx(s); 2138115Sroot } 2147422Sroot retry: 2157422Sroot ncoll = nselcoll; 2167422Sroot u.u_procp->p_flag |= SSEL; 2178115Sroot u.u_r.r_val1 = selscan(ibits, obits); 2187422Sroot if (u.u_error) 2198115Sroot return; 2208115Sroot if (u.u_r.r_val1) 2217422Sroot goto done; 2228115Sroot s = spl6(); 2238145Sroot if (uap->tv && timercmp(&time, &atv, >=)) { 2248115Sroot splx(s); 2257422Sroot goto done; 2268115Sroot } 2277422Sroot if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 2287422Sroot u.u_procp->p_flag &= ~SSEL; 2297422Sroot splx(s); 2307422Sroot goto retry; 2317422Sroot } 2327422Sroot u.u_procp->p_flag &= ~SSEL; 2338115Sroot if (uap->tv) { 2348115Sroot lqsave = u.u_qsave; 2358115Sroot if (setjmp(&u.u_qsave)) { 236*8622Sroot untimeout(unselect, (caddr_t)u.u_procp); 2378115Sroot u.u_error = EINTR; 2388115Sroot splx(s); 2398115Sroot return; 2408115Sroot } 241*8622Sroot timeout(unselect, (caddr_t)u.u_procp, hzto(&atv)); 2428115Sroot } 2438115Sroot sleep((caddr_t)&selwait, PZERO+1); 2448115Sroot if (uap->tv) { 2458115Sroot u.u_qsave = lqsave; 246*8622Sroot untimeout(unselect, (caddr_t)u.u_procp); 2478115Sroot } 2487422Sroot splx(s); 2498115Sroot goto retry; 2508115Sroot done: 2518145Sroot #define putbits(name, x) \ 2528145Sroot if (uap->name) { \ 2538145Sroot if (copyout((caddr_t)obits[x], (caddr_t)uap->name, \ 2548145Sroot sizeof (obits[x]))) { \ 2558145Sroot u.u_error = EFAULT; \ 2568145Sroot return; \ 2578145Sroot } \ 2588115Sroot } 2598145Sroot putbits(in, 0); 2608145Sroot putbits(ou, 1); 2618145Sroot putbits(ex, 2); 2628145Sroot #undef putbits 2638115Sroot } 2647422Sroot 2658115Sroot unselect(p) 2668115Sroot register struct proc *p; 2678115Sroot { 2688115Sroot register int s = spl6(); 2697422Sroot 2708115Sroot switch (p->p_stat) { 2717422Sroot 2728115Sroot case SSLEEP: 2738115Sroot setrun(p); 2747422Sroot break; 2758115Sroot 2768115Sroot case SSTOP: 2778115Sroot unsleep(p); 2788115Sroot break; 2797422Sroot } 2808115Sroot splx(s); 2817422Sroot } 2827422Sroot 2838115Sroot selscan(ibits, obits) 2848115Sroot int *ibits, *obits; 2857422Sroot { 2868115Sroot register int which, bits, i; 2878115Sroot int flag; 2887422Sroot struct file *fp; 2898115Sroot int able; 2907422Sroot struct inode *ip; 2918115Sroot int n = 0; 2927422Sroot 2938115Sroot for (which = 0; which < 3; which++) { 2948115Sroot bits = ibits[which]; 2958115Sroot obits[which] = 0; 2968115Sroot switch (which) { 2977422Sroot 2988115Sroot case 0: 2998115Sroot flag = FREAD; break; 3008115Sroot 3018115Sroot case 1: 3028115Sroot flag = FWRITE; break; 3038115Sroot 3048115Sroot case 2: 3058115Sroot flag = 0; break; 3068115Sroot } 3078115Sroot while (i = ffs(bits)) { 3088115Sroot bits &= ~(1<<(i-1)); 3098115Sroot fp = u.u_ofile[i-1]; 3108115Sroot if (fp == NULL) { 3118115Sroot u.u_error = EBADF; 3127422Sroot break; 3137422Sroot } 3148115Sroot if (fp->f_type == DTYPE_SOCKET) 3158115Sroot able = soselect(fp->f_socket, flag); 3168115Sroot else { 3178115Sroot ip = fp->f_inode; 3188115Sroot switch (ip->i_mode & IFMT) { 3197497Sroot 3208115Sroot case IFCHR: 3218115Sroot able = 3228115Sroot (*cdevsw[major(ip->i_rdev)].d_select) 3238115Sroot (ip->i_rdev, flag); 3248115Sroot break; 3258115Sroot 3268115Sroot case IFBLK: 3278115Sroot case IFREG: 3288115Sroot case IFDIR: 3298115Sroot able = 1; 3308115Sroot break; 3318115Sroot } 3328115Sroot 3338115Sroot } 3348115Sroot if (able) { 3358115Sroot obits[which] |= (1<<(i-1)); 3368115Sroot n++; 3378115Sroot } 3387422Sroot } 3397422Sroot } 3408115Sroot return (n); 3417422Sroot } 3427422Sroot 3437422Sroot /*ARGSUSED*/ 3447422Sroot seltrue(dev, flag) 3457422Sroot dev_t dev; 3467422Sroot int flag; 3477422Sroot { 3487422Sroot 3497422Sroot return (1); 3507422Sroot } 3517422Sroot 3527422Sroot selwakeup(p, coll) 3537422Sroot register struct proc *p; 3547422Sroot int coll; 3557422Sroot { 3567422Sroot int s; 3577422Sroot 3587422Sroot if (coll) { 3597422Sroot nselcoll++; 3607422Sroot wakeup((caddr_t)&selwait); 3617422Sroot } 3627422Sroot if (p) { 3637422Sroot if (p->p_wchan == (caddr_t)&selwait) 3647422Sroot setrun(p); 3657422Sroot else { 3667422Sroot s = spl6(); 3677422Sroot if (p->p_flag & SSEL) 3687422Sroot p->p_flag &= ~SSEL; 3697422Sroot splx(s); 3707422Sroot } 3717422Sroot } 3727422Sroot } 3737422Sroot 3748029Sroot revoke() 3758029Sroot { 3768029Sroot 3778029Sroot /* XXX */ 3788029Sroot } 3798029Sroot 3807422Sroot /* 3817497Sroot * Allocate a user file descriptor. 3827422Sroot */ 3837497Sroot ufalloc() 3847422Sroot { 3857497Sroot register i; 3867497Sroot 3877497Sroot for (i=0; i<NOFILE; i++) 3887497Sroot if (u.u_ofile[i] == NULL) { 3897497Sroot u.u_r.r_val1 = i; 3907497Sroot u.u_pofile[i] = 0; 3917497Sroot return (i); 3927497Sroot } 3937497Sroot u.u_error = EMFILE; 3947497Sroot return (-1); 3957497Sroot } 3967497Sroot 3977497Sroot struct file *lastf; 3987497Sroot /* 3997497Sroot * Allocate a user file descriptor 4007497Sroot * and a file structure. 4017497Sroot * Initialize the descriptor 4027497Sroot * to point at the file structure. 4037497Sroot */ 4047497Sroot struct file * 4057497Sroot falloc() 4067497Sroot { 4077422Sroot register struct file *fp; 4087497Sroot register i; 4097422Sroot 4107497Sroot i = ufalloc(); 4117497Sroot if (i < 0) 4127497Sroot return (NULL); 4137497Sroot if (lastf == 0) 4147497Sroot lastf = file; 4157497Sroot for (fp = lastf; fp < fileNFILE; fp++) 4167497Sroot if (fp->f_count == 0) 4177497Sroot goto slot; 4187497Sroot for (fp = file; fp < lastf; fp++) 4197497Sroot if (fp->f_count == 0) 4207497Sroot goto slot; 4217497Sroot tablefull("file"); 4227497Sroot u.u_error = ENFILE; 4237497Sroot return (NULL); 4247497Sroot slot: 4257497Sroot u.u_ofile[i] = fp; 4267497Sroot fp->f_count++; 4277497Sroot fp->f_offset = 0; 4287497Sroot fp->f_inode = 0; 4297497Sroot lastf = fp + 1; 4307497Sroot return (fp); 4317497Sroot } 4327497Sroot /* 4337497Sroot * Convert a user supplied file descriptor into a pointer 4347497Sroot * to a file structure. Only task is to check range of the descriptor. 4357497Sroot * Critical paths should use the GETF macro, defined in inline.h. 4367497Sroot */ 4377497Sroot struct file * 4387497Sroot getf(f) 4397497Sroot register int f; 4407497Sroot { 4417497Sroot register struct file *fp; 4427497Sroot 4437497Sroot if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 4447497Sroot u.u_error = EBADF; 4457497Sroot return (NULL); 4467497Sroot } 4477497Sroot return (fp); 4487497Sroot } 4497497Sroot 4507497Sroot /* 4517497Sroot * Internal form of close. 4527497Sroot * Decrement reference count on 4537497Sroot * file structure. 4547497Sroot * Also make sure the pipe protocol 4557497Sroot * does not constipate. 4567497Sroot * 4577497Sroot * Decrement reference count on the inode following 4587497Sroot * removal to the referencing file structure. 4597497Sroot * Call device handler on last close. 4607497Sroot * Nouser indicates that the user isn't available to present 4617497Sroot * errors to. 4627696Ssam * 4637696Ssam * Handling locking at this level is RIDICULOUS. 4647497Sroot */ 4657696Ssam closef(fp, nouser, flags) 4667497Sroot register struct file *fp; 4677696Ssam int nouser, flags; 4687497Sroot { 4697497Sroot register struct inode *ip; 4707497Sroot register struct mount *mp; 4717497Sroot int flag, mode; 4727497Sroot dev_t dev; 4737497Sroot register int (*cfunc)(); 4747497Sroot 4757422Sroot if (fp == NULL) 4767422Sroot return; 4777497Sroot if (fp->f_count > 1) { 4787497Sroot fp->f_count--; 4797422Sroot return; 4807422Sroot } 4817497Sroot if (fp->f_type == DTYPE_SOCKET) { 4827497Sroot u.u_error = 0; /* XXX */ 4837497Sroot soclose(fp->f_socket, nouser); 4847497Sroot if (nouser == 0 && u.u_error) 4857497Sroot return; 4867497Sroot fp->f_socket = 0; 4877497Sroot fp->f_count = 0; 4887497Sroot return; 4897497Sroot } 4907497Sroot flag = fp->f_flag; 4917497Sroot ip = fp->f_inode; 4927497Sroot dev = (dev_t)ip->i_rdev; 4937497Sroot mode = ip->i_mode & IFMT; 4947696Ssam flags &= RDLOCK|WRLOCK; /* conservative */ 4957696Ssam if (flags) 4967696Ssam funlocki(ip, flags); 4977497Sroot ilock(ip); 4987497Sroot iput(ip); 4997497Sroot fp->f_count = 0; 5007497Sroot 5017497Sroot switch (mode) { 5027497Sroot 5037497Sroot case IFCHR: 5047497Sroot cfunc = cdevsw[major(dev)].d_close; 5057497Sroot break; 5067497Sroot 5077497Sroot case IFBLK: 5087497Sroot /* 5097497Sroot * We don't want to really close the device if it is mounted 5107497Sroot */ 5117497Sroot for (mp = mount; mp < &mount[NMOUNT]; mp++) 5127497Sroot if (mp->m_bufp != NULL && mp->m_dev == dev) 5137497Sroot return; 5147497Sroot cfunc = bdevsw[major(dev)].d_close; 5157497Sroot break; 5167497Sroot 5177497Sroot default: 5187497Sroot return; 5197497Sroot } 5207497Sroot for (fp = file; fp < fileNFILE; fp++) { 5217497Sroot if (fp->f_type == DTYPE_SOCKET) /* XXX */ 5227497Sroot continue; 5237497Sroot if (fp->f_count && (ip = fp->f_inode) && 5247497Sroot ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 5257497Sroot return; 5267497Sroot } 5277497Sroot if (mode == IFBLK) { 5287497Sroot /* 5297497Sroot * On last close of a block device (that isn't mounted) 5307497Sroot * we must invalidate any in core blocks 5317497Sroot */ 5327497Sroot bflush(dev); 5337497Sroot binval(dev); 5347497Sroot } 5357497Sroot (*cfunc)(dev, flag, fp); 5367422Sroot } 5378119Sroot 5388119Sroot opause() 5398119Sroot { 5408119Sroot 5418119Sroot for (;;) 5428119Sroot sleep((caddr_t)&u, PSLEP); 5438119Sroot } 544