1 /* kern_descrip.c 5.8 82/09/08 */ 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 unselect(); 167 int nselcoll; 168 /* 169 * Select system call. 170 */ 171 select() 172 { 173 register struct uap { 174 long *ibits; 175 long *obits; 176 struct timeval *tv; 177 } *uap = (struct uap *)u.u_ap; 178 int ibits[3], obits[3]; 179 struct timeval atv; 180 int s, tsel, ncoll, rem; 181 label_t lqsave; 182 183 if (uap->tv) { 184 if (copyin((caddr_t)uap->tv, (caddr_t)&atv, sizeof (atv))) { 185 u.u_error = EFAULT; 186 return; 187 } 188 if (itimerfix(&atv)) { 189 u.u_error = EINVAL; 190 return; 191 } 192 s = spl7(); timevaladd(&atv, &time); splx(s); 193 } 194 if (copyin((caddr_t)uap->ibits, (caddr_t)ibits, sizeof (ibits))) { 195 u.u_error = EFAULT; 196 return; 197 } 198 retry: 199 ncoll = nselcoll; 200 u.u_procp->p_flag |= SSEL; 201 u.u_r.r_val1 = selscan(ibits, obits); 202 if (u.u_error) 203 return; 204 if (u.u_r.r_val1) 205 goto done; 206 s = spl6(); 207 if (uap->tv && timercmp(&atv, &time, >=)) { 208 splx(s); 209 goto done; 210 } 211 if ((u.u_procp->p_flag & SSEL) == 0 || nselcoll != ncoll) { 212 u.u_procp->p_flag &= ~SSEL; 213 splx(s); 214 goto retry; 215 } 216 u.u_procp->p_flag &= ~SSEL; 217 if (uap->tv) { 218 lqsave = u.u_qsave; 219 if (setjmp(&u.u_qsave)) { 220 untimeout(unselect, u.u_procp); 221 u.u_error = EINTR; 222 splx(s); 223 return; 224 } 225 timeout(unselect, u.u_procp, hzto(&atv)); 226 } 227 sleep((caddr_t)&selwait, PZERO+1); 228 if (uap->tv) { 229 u.u_qsave = lqsave; 230 untimeout(unselect, u.u_procp); 231 } 232 splx(s); 233 goto retry; 234 done: 235 if (copyout((caddr_t)obits, (caddr_t)uap->obits, sizeof (obits))) { 236 u.u_error = EFAULT; 237 return; 238 } 239 } 240 241 unselect(p) 242 register struct proc *p; 243 { 244 register int s = spl6(); 245 246 switch (p->p_stat) { 247 248 case SSLEEP: 249 setrun(p); 250 break; 251 252 case SSTOP: 253 unsleep(p); 254 break; 255 } 256 splx(s); 257 } 258 259 selscan(ibits, obits) 260 int *ibits, *obits; 261 { 262 register int which, bits, i; 263 int flag; 264 struct file *fp; 265 int able; 266 struct inode *ip; 267 int n = 0; 268 269 for (which = 0; which < 3; which++) { 270 bits = ibits[which]; 271 obits[which] = 0; 272 switch (which) { 273 274 case 0: 275 flag = FREAD; break; 276 277 case 1: 278 flag = FWRITE; break; 279 280 case 2: 281 flag = 0; break; 282 } 283 while (i = ffs(bits)) { 284 bits &= ~(1<<(i-1)); 285 fp = u.u_ofile[i-1]; 286 if (fp == NULL) { 287 u.u_error = EBADF; 288 break; 289 } 290 if (fp->f_type == DTYPE_SOCKET) 291 able = soselect(fp->f_socket, flag); 292 else { 293 ip = fp->f_inode; 294 switch (ip->i_mode & IFMT) { 295 296 case IFCHR: 297 able = 298 (*cdevsw[major(ip->i_rdev)].d_select) 299 (ip->i_rdev, flag); 300 break; 301 302 case IFBLK: 303 case IFREG: 304 case IFDIR: 305 able = 1; 306 break; 307 } 308 309 } 310 if (able) { 311 obits[which] |= (1<<(i-1)); 312 n++; 313 } 314 } 315 } 316 return (n); 317 } 318 319 /*ARGSUSED*/ 320 seltrue(dev, flag) 321 dev_t dev; 322 int flag; 323 { 324 325 return (1); 326 } 327 328 selwakeup(p, coll) 329 register struct proc *p; 330 int coll; 331 { 332 int s; 333 334 if (coll) { 335 nselcoll++; 336 wakeup((caddr_t)&selwait); 337 } 338 if (p) { 339 if (p->p_wchan == (caddr_t)&selwait) 340 setrun(p); 341 else { 342 s = spl6(); 343 if (p->p_flag & SSEL) 344 p->p_flag &= ~SSEL; 345 splx(s); 346 } 347 } 348 } 349 350 revoke() 351 { 352 353 /* XXX */ 354 } 355 356 /* 357 * Allocate a user file descriptor. 358 */ 359 ufalloc() 360 { 361 register i; 362 363 for (i=0; i<NOFILE; i++) 364 if (u.u_ofile[i] == NULL) { 365 u.u_r.r_val1 = i; 366 u.u_pofile[i] = 0; 367 return (i); 368 } 369 u.u_error = EMFILE; 370 return (-1); 371 } 372 373 struct file *lastf; 374 /* 375 * Allocate a user file descriptor 376 * and a file structure. 377 * Initialize the descriptor 378 * to point at the file structure. 379 */ 380 struct file * 381 falloc() 382 { 383 register struct file *fp; 384 register i; 385 386 i = ufalloc(); 387 if (i < 0) 388 return (NULL); 389 if (lastf == 0) 390 lastf = file; 391 for (fp = lastf; fp < fileNFILE; fp++) 392 if (fp->f_count == 0) 393 goto slot; 394 for (fp = file; fp < lastf; fp++) 395 if (fp->f_count == 0) 396 goto slot; 397 tablefull("file"); 398 u.u_error = ENFILE; 399 return (NULL); 400 slot: 401 u.u_ofile[i] = fp; 402 fp->f_count++; 403 fp->f_offset = 0; 404 fp->f_inode = 0; 405 lastf = fp + 1; 406 return (fp); 407 } 408 /* 409 * Convert a user supplied file descriptor into a pointer 410 * to a file structure. Only task is to check range of the descriptor. 411 * Critical paths should use the GETF macro, defined in inline.h. 412 */ 413 struct file * 414 getf(f) 415 register int f; 416 { 417 register struct file *fp; 418 419 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 420 u.u_error = EBADF; 421 return (NULL); 422 } 423 return (fp); 424 } 425 426 /* 427 * Internal form of close. 428 * Decrement reference count on 429 * file structure. 430 * Also make sure the pipe protocol 431 * does not constipate. 432 * 433 * Decrement reference count on the inode following 434 * removal to the referencing file structure. 435 * Call device handler on last close. 436 * Nouser indicates that the user isn't available to present 437 * errors to. 438 * 439 * Handling locking at this level is RIDICULOUS. 440 */ 441 closef(fp, nouser, flags) 442 register struct file *fp; 443 int nouser, flags; 444 { 445 register struct inode *ip; 446 register struct mount *mp; 447 int flag, mode; 448 dev_t dev; 449 register int (*cfunc)(); 450 451 if (fp == NULL) 452 return; 453 if (fp->f_count > 1) { 454 fp->f_count--; 455 return; 456 } 457 if (fp->f_type == DTYPE_SOCKET) { 458 u.u_error = 0; /* XXX */ 459 soclose(fp->f_socket, nouser); 460 if (nouser == 0 && u.u_error) 461 return; 462 fp->f_socket = 0; 463 fp->f_count = 0; 464 return; 465 } 466 flag = fp->f_flag; 467 ip = fp->f_inode; 468 dev = (dev_t)ip->i_rdev; 469 mode = ip->i_mode & IFMT; 470 flags &= RDLOCK|WRLOCK; /* conservative */ 471 if (flags) 472 funlocki(ip, flags); 473 ilock(ip); 474 iput(ip); 475 fp->f_count = 0; 476 477 switch (mode) { 478 479 case IFCHR: 480 cfunc = cdevsw[major(dev)].d_close; 481 break; 482 483 case IFBLK: 484 /* 485 * We don't want to really close the device if it is mounted 486 */ 487 for (mp = mount; mp < &mount[NMOUNT]; mp++) 488 if (mp->m_bufp != NULL && mp->m_dev == dev) 489 return; 490 cfunc = bdevsw[major(dev)].d_close; 491 break; 492 493 default: 494 return; 495 } 496 for (fp = file; fp < fileNFILE; fp++) { 497 if (fp->f_type == DTYPE_SOCKET) /* XXX */ 498 continue; 499 if (fp->f_count && (ip = fp->f_inode) && 500 ip->i_rdev == dev && (ip->i_mode&IFMT) == mode) 501 return; 502 } 503 if (mode == IFBLK) { 504 /* 505 * On last close of a block device (that isn't mounted) 506 * we must invalidate any in core blocks 507 */ 508 bflush(dev); 509 binval(dev); 510 } 511 (*cfunc)(dev, flag, fp); 512 } 513