1 /* kern_descrip.c 5.7 82/09/06 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/kernel.h" 8 #include "../h/inode.h" 9 #include "../h/proc.h" 10 #include "../h/conf.h" 11 #include "../h/file.h" 12 #include "../h/inline.h" 13 #include "../h/socket.h" 14 #include "../h/socketvar.h" 15 #include "../h/mount.h" 16 17 #include "../h/descrip.h" 18 19 /* 20 * Descriptor management. 21 */ 22 23 /* 24 * TODO: 25 * getf should be renamed 26 * ufalloc side effects are gross 27 */ 28 29 /* 30 * System calls on descriptors. 31 */ 32 getdtablesize() 33 { 34 35 u.u_r.r_val1 = NOFILE; 36 } 37 38 getdprop() 39 { 40 register struct a { 41 int d; 42 struct dtype *dtypeb; 43 } *uap = (struct a *)u.u_ap; 44 register struct file *fp; 45 struct dtype adtype; 46 47 fp = getf(uap->d); 48 if (fp == 0) 49 return; 50 adtype.dt_type = 0; /* XXX */ 51 adtype.dt_protocol = 0; /* XXX */ 52 if (copyout((caddr_t)&adtype, (caddr_t)uap->dtypeb, 53 sizeof (struct dtype)) < 0) { 54 u.u_error = EFAULT; 55 return; 56 } 57 } 58 59 getdopt() 60 { 61 62 } 63 64 setdopt() 65 { 66 67 } 68 69 dup() 70 { 71 register struct a { 72 int i; 73 } *uap = (struct a *) u.u_ap; 74 struct file *fp; 75 int j; 76 77 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 78 79 fp = getf(uap->i); 80 if (fp == 0) 81 return; 82 j = ufalloc(); 83 if (j < 0) 84 return; 85 dupit(j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 86 } 87 88 dup2() 89 { 90 register struct a { 91 int i, j; 92 } *uap = (struct a *) u.u_ap; 93 register struct file *fp; 94 95 fp = getf(uap->i); 96 if (fp == 0) 97 return; 98 if (uap->j < 0 || uap->j >= NOFILE) { 99 u.u_error = EBADF; 100 return; 101 } 102 u.u_r.r_val1 = uap->j; 103 if (uap->i == uap->j) 104 return; 105 if (u.u_ofile[uap->j]) { 106 closef(u.u_ofile[uap->j], 0, u.u_pofile[uap->j]); 107 if (u.u_error) 108 return; 109 /* u.u_ofile[uap->j] = 0; */ 110 /* u.u_pofile[uap->j] = 0; */ 111 } 112 dupit(uap->j, fp, u.u_pofile[uap->i] & (RDLOCK|WRLOCK)); 113 } 114 115 dupit(fd, fp, lockflags) 116 int fd; 117 register struct file *fp; 118 register int lockflags; 119 { 120 121 u.u_ofile[fd] = fp; 122 u.u_pofile[fd] = lockflags; 123 fp->f_count++; 124 if (lockflags&RDLOCK) 125 fp->f_inode->i_rdlockc++; 126 if (lockflags&WRLOCK) 127 fp->f_inode->i_wrlockc++; 128 } 129 130 close() 131 { 132 register struct a { 133 int i; 134 } *uap = (struct a *)u.u_ap; 135 register struct file *fp; 136 137 fp = getf(uap->i); 138 if (fp == 0) 139 return; 140 closef(fp, 0, u.u_pofile[uap->i]); 141 /* WHAT IF u.u_error ? */ 142 u.u_ofile[uap->i] = NULL; 143 u.u_pofile[uap->i] = 0; 144 } 145 146 wrap() 147 { 148 register struct a { 149 int d; 150 struct dtype *dtypeb; 151 } *uap = (struct a *)u.u_ap; 152 register struct file *fp; 153 struct dtype adtype; 154 155 fp = getf(uap->d); 156 if (fp == 0) 157 return; 158 if (copyin((caddr_t)uap->dtypeb, (caddr_t)&adtype, 159 sizeof (struct dtype)) < 0) { 160 u.u_error = EFAULT; 161 return; 162 } 163 /* DO WRAP */ 164 } 165 166 int nselcoll; 167 /* 168 * Select system call. 169 */ 170 select() 171 { 172 register struct uap { 173 fd_set *rp, *wp, *ep; 174 struct timeval *tv; 175 } *uap = (struct uap *)u.u_ap; 176 fd_set rd, wr; 177 int nfds = 0, readable = 0, writeable = 0; 178 struct timeval atv, origin, now; 179 int s, tsel, ncoll, rem; 180 181 if (uap->tv) { 182 if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 183 u.u_error = EFAULT; 184 return; 185 } 186 } else 187 timerclear(&atv); 188 if (uap->rp && copyin((caddr_t)uap->rp,(caddr_t)&rd,sizeof(fd_set))) 189 return; 190 if (uap->wp && copyin((caddr_t)uap->wp,(caddr_t)&wr,sizeof(fd_set))) 191 return; 192 retry: 193 s = spl7(); now = time; splx(s); 194 ncoll = nselcoll; 195 u.u_procp->p_flag |= SSEL; 196 if (uap->rp) 197 readable = selscan(rd, &nfds, FREAD); 198 if (uap->wp) 199 writeable = selscan(wr, &nfds, FWRITE); 200 if (u.u_error) 201 goto done; 202 if (readable || writeable) 203 goto done; 204 if (!timerisset(&atv)) 205 goto done; 206 s = spl6(); 207 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 208 u.u_procp->p_flag &= ~SSEL; 209 splx(s); 210 goto retry; 211 } 212 u.u_procp->p_flag &= ~SSEL; 213 tsel = tsleep((caddr_t)&selwait, PZERO+1, &atv); 214 splx(s); 215 switch (tsel) { 216 217 case TS_OK: 218 now = time; 219 timevalsub(&now, &origin); 220 timevalsub(&atv, now); 221 if (atv.tv_sec < 0 || atv.tv_usec < 0) 222 timerclear(&atv); 223 goto retry; 224 225 case TS_SIG: 226 u.u_error = EINTR; 227 return; 228 229 case TS_TIME: 230 break; 231 } 232 done: 233 rd.fds_bits[0] = readable; 234 wr.fds_bits[0] = writeable; 235 s = sizeof (fd_set); 236 u.u_r.r_val1 = nfds; 237 if (uap->rp) 238 (void) copyout((caddr_t)&rd, (caddr_t)uap->rp, sizeof(fd_set)); 239 if (uap->wp) 240 (void) copyout((caddr_t)&wr, (caddr_t)uap->wp, sizeof(fd_set)); 241 } 242 243 selscan(fds, nfdp, flag) 244 fd_set fds; 245 int *nfdp, flag; 246 { 247 struct file *fp; 248 struct inode *ip; 249 register int bits; 250 int i, able, res = 0; 251 252 bits = fds.fds_bits[0]; 253 while (i = ffs(bits)) { 254 bits &= ~(1<<(i-1)); 255 fp = u.u_ofile[i-1]; 256 if (fp == NULL) { 257 u.u_error = EBADF; 258 return (0); 259 } 260 if (fp->f_type == DTYPE_SOCKET) 261 able = soselect(fp->f_socket, flag); 262 else { 263 ip = fp->f_inode; 264 switch (ip->i_mode & IFMT) { 265 266 case IFCHR: 267 able = 268 (*cdevsw[major(ip->i_rdev)].d_select) 269 (ip->i_rdev, flag); 270 break; 271 272 case IFBLK: 273 case IFREG: 274 case IFDIR: 275 able = 1; 276 break; 277 } 278 279 } 280 if (able) { 281 res |= (1<<(i-1)); 282 (*nfdp)++; 283 } 284 } 285 return (res); 286 } 287 288 /*ARGSUSED*/ 289 seltrue(dev, flag) 290 dev_t dev; 291 int flag; 292 { 293 294 return (1); 295 } 296 297 selwakeup(p, coll) 298 register struct proc *p; 299 int coll; 300 { 301 int s; 302 303 if (coll) { 304 nselcoll++; 305 wakeup((caddr_t)&selwait); 306 } 307 if (p) { 308 if (p->p_wchan == (caddr_t)&selwait) 309 setrun(p); 310 else { 311 s = spl6(); 312 if (p->p_flag & SSEL) 313 p->p_flag &= ~SSEL; 314 splx(s); 315 } 316 } 317 } 318 319 revoke() 320 { 321 322 /* XXX */ 323 } 324 325 /* 326 * Allocate a user file descriptor. 327 */ 328 ufalloc() 329 { 330 register i; 331 332 for (i=0; i<NOFILE; i++) 333 if (u.u_ofile[i] == NULL) { 334 u.u_r.r_val1 = i; 335 u.u_pofile[i] = 0; 336 return (i); 337 } 338 u.u_error = EMFILE; 339 return (-1); 340 } 341 342 struct file *lastf; 343 /* 344 * Allocate a user file descriptor 345 * and a file structure. 346 * Initialize the descriptor 347 * to point at the file structure. 348 */ 349 struct file * 350 falloc() 351 { 352 register struct file *fp; 353 register i; 354 355 i = ufalloc(); 356 if (i < 0) 357 return (NULL); 358 if (lastf == 0) 359 lastf = file; 360 for (fp = lastf; fp < fileNFILE; fp++) 361 if (fp->f_count == 0) 362 goto slot; 363 for (fp = file; fp < lastf; fp++) 364 if (fp->f_count == 0) 365 goto slot; 366 tablefull("file"); 367 u.u_error = ENFILE; 368 return (NULL); 369 slot: 370 u.u_ofile[i] = fp; 371 fp->f_count++; 372 fp->f_offset = 0; 373 fp->f_inode = 0; 374 lastf = fp + 1; 375 return (fp); 376 } 377 /* 378 * Convert a user supplied file descriptor into a pointer 379 * to a file structure. Only task is to check range of the descriptor. 380 * Critical paths should use the GETF macro, defined in inline.h. 381 */ 382 struct file * 383 getf(f) 384 register int f; 385 { 386 register struct file *fp; 387 388 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 389 u.u_error = EBADF; 390 return (NULL); 391 } 392 return (fp); 393 } 394 395 /* 396 * Internal form of close. 397 * Decrement reference count on 398 * file structure. 399 * Also make sure the pipe protocol 400 * does not constipate. 401 * 402 * Decrement reference count on the inode following 403 * removal to the referencing file structure. 404 * Call device handler on last close. 405 * Nouser indicates that the user isn't available to present 406 * errors to. 407 * 408 * Handling locking at this level is RIDICULOUS. 409 */ 410 closef(fp, nouser, flags) 411 register struct file *fp; 412 int nouser, flags; 413 { 414 register struct inode *ip; 415 register struct mount *mp; 416 int flag, mode; 417 dev_t dev; 418 register int (*cfunc)(); 419 420 if (fp == NULL) 421 return; 422 if (fp->f_count > 1) { 423 fp->f_count--; 424 return; 425 } 426 if (fp->f_type == DTYPE_SOCKET) { 427 u.u_error = 0; /* XXX */ 428 soclose(fp->f_socket, nouser); 429 if (nouser == 0 && u.u_error) 430 return; 431 fp->f_socket = 0; 432 fp->f_count = 0; 433 return; 434 } 435 flag = fp->f_flag; 436 ip = fp->f_inode; 437 dev = (dev_t)ip->i_rdev; 438 mode = ip->i_mode & IFMT; 439 flags &= RDLOCK|WRLOCK; /* conservative */ 440 if (flags) 441 funlocki(ip, flags); 442 ilock(ip); 443 iput(ip); 444 fp->f_count = 0; 445 446 switch (mode) { 447 448 case IFCHR: 449 cfunc = cdevsw[major(dev)].d_close; 450 break; 451 452 case IFBLK: 453 /* 454 * We don't want to really close the device if it is mounted 455 */ 456 for (mp = mount; mp < &mount[NMOUNT]; mp++) 457 if (mp->m_bufp != NULL && mp->m_dev == dev) 458 return; 459 cfunc = bdevsw[major(dev)].d_close; 460 break; 461 462 default: 463 return; 464 } 465 for (fp = file; fp < fileNFILE; fp++) { 466 if (fp->f_type == DTYPE_SOCKET) /* XXX */ 467 continue; 468 if (fp->f_count && (ip = fp->f_inode) && 469 ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 470 return; 471 } 472 if (mode == IFBLK) { 473 /* 474 * On last close of a block device (that isn't mounted) 475 * we must invalidate any in core blocks 476 */ 477 bflush(dev); 478 binval(dev); 479 } 480 (*cfunc)(dev, flag, fp); 481 } 482