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