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