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