1 /* kern_descrip.c 5.25 83/06/12 */ 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/socket.h" 13 #include "../h/socketvar.h" 14 #include "../h/mount.h" 15 #include "../h/stat.h" 16 17 #include "../h/ioctl.h" 18 19 /* 20 * Descriptor management. 21 */ 22 23 /* 24 * TODO: 25 * increase NOFILE 26 * eliminate u.u_error side effects 27 */ 28 29 /* 30 * System calls on descriptors. 31 */ 32 getdtablesize() 33 { 34 35 u.u_r.r_val1 = NOFILE; 36 } 37 38 getdopt() 39 { 40 41 } 42 43 setdopt() 44 { 45 46 } 47 48 dup() 49 { 50 register struct a { 51 int i; 52 } *uap = (struct a *) u.u_ap; 53 struct file *fp; 54 int j; 55 56 if (uap->i &~ 077) { uap->i &= 077; dup2(); return; } /* XXX */ 57 58 fp = getf(uap->i); 59 if (fp == 0) 60 return; 61 j = ufalloc(0); 62 if (j < 0) 63 return; 64 dupit(j, fp, u.u_pofile[uap->i]); 65 } 66 67 dup2() 68 { 69 register struct a { 70 int i, j; 71 } *uap = (struct a *) u.u_ap; 72 register struct file *fp; 73 74 fp = getf(uap->i); 75 if (fp == 0) 76 return; 77 if (uap->j < 0 || uap->j >= NOFILE) { 78 u.u_error = EBADF; 79 return; 80 } 81 u.u_r.r_val1 = uap->j; 82 if (uap->i == uap->j) 83 return; 84 if (u.u_ofile[uap->j]) { 85 if (u.u_pofile[uap->j] & UF_MAPPED) 86 munmapfd(uap->j); 87 closef(u.u_ofile[uap->j], u.u_pofile[uap->j]); 88 if (u.u_error) 89 return; 90 /* u.u_ofile[uap->j] = 0; */ 91 /* u.u_pofile[uap->j] = 0; */ 92 } 93 dupit(uap->j, fp, u.u_pofile[uap->i]); 94 } 95 96 dupit(fd, fp, lockflags) 97 int fd; 98 register struct file *fp; 99 register int lockflags; 100 { 101 102 u.u_ofile[fd] = fp; 103 u.u_pofile[fd] = lockflags; 104 fp->f_count++; 105 /* THIS DOESN'T BELONG HERE */ 106 if (lockflags&UF_SHLOCK) 107 ((struct inode *)fp->f_data)->i_shlockc++; 108 if (lockflags&UF_EXLOCK) 109 ((struct inode *)fp->f_data)->i_exlockc++; 110 /* END DOESN'T BELONG */ 111 } 112 113 /* 114 * The file control system call. 115 */ 116 fcntl() 117 { 118 register struct file *fp; 119 register struct a { 120 int fdes; 121 int cmd; 122 int arg; 123 } *uap; 124 register i; 125 register char *pop; 126 127 uap = (struct a *)u.u_ap; 128 fp = getf(uap->fdes); 129 if (fp == NULL) 130 return; 131 pop = &u.u_pofile[uap->fdes]; 132 switch(uap->cmd) { 133 case 0: 134 i = uap->arg; 135 if (i < 0 || i > NOFILE) { 136 u.u_error = EINVAL; 137 return; 138 } 139 if ((i = ufalloc(i)) < 0) 140 return; 141 dupit(i, fp, *pop); 142 break; 143 144 case 1: 145 u.u_r.r_val1 = *pop & 1; 146 break; 147 148 case 2: 149 *pop = (*pop &~ 1) | (uap->arg & 1); 150 break; 151 152 case 3: 153 u.u_r.r_val1 = fp->f_flag+FOPEN; 154 break; 155 156 case 4: 157 fp->f_flag &= FCNTLCANT; 158 fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 159 u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); 160 if (u.u_error) 161 break; 162 u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 163 if (u.u_error) 164 (void) fset(fp, FNDELAY, 0); 165 break; 166 167 case 5: 168 u.u_error = fsetown(fp, uap->arg); 169 break; 170 171 case 6: 172 u.u_error = fgetown(fp, &u.u_r.r_val1); 173 break; 174 175 default: 176 u.u_error = EINVAL; 177 } 178 } 179 180 fset(fp, bit, value) 181 struct file *fp; 182 int bit, value; 183 { 184 185 if (value) 186 fp->f_flag |= bit; 187 else 188 fp->f_flag &= ~bit; 189 return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 190 (caddr_t)&value)); 191 } 192 193 fgetown(fp, valuep) 194 struct file *fp; 195 int *valuep; 196 { 197 int error; 198 199 switch (fp->f_type) { 200 201 case DTYPE_SOCKET: 202 *valuep = ((struct socket *)fp->f_data)->so_pgrp; 203 return (0); 204 205 default: 206 error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 207 *valuep = -*valuep; 208 return (error); 209 } 210 } 211 212 fsetown(fp, value) 213 struct file *fp; 214 int value; 215 { 216 217 if (fp->f_type == DTYPE_SOCKET) { 218 ((struct socket *)fp->f_data)->so_pgrp = value; 219 return (0); 220 } 221 if (value > 0) { 222 struct proc *p = pfind(value); 223 if (p == 0) 224 return (EINVAL); 225 value = p->p_pgrp; 226 } else 227 value = -value; 228 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 229 } 230 231 fioctl(fp, cmd, value) 232 struct file *fp; 233 int cmd; 234 caddr_t value; 235 { 236 237 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 238 } 239 240 close() 241 { 242 register struct a { 243 int i; 244 } *uap = (struct a *)u.u_ap; 245 register struct file *fp; 246 register u_char *pf; 247 248 fp = getf(uap->i); 249 if (fp == 0) 250 return; 251 pf = (u_char *)&u.u_pofile[uap->i]; 252 if (*pf & UF_MAPPED) 253 munmapfd(uap->i); 254 if (*pf & (UF_SHLOCK|UF_EXLOCK)) 255 unlockf(fp, pf); 256 closef(fp); 257 /* WHAT IF u.u_error ? */ 258 u.u_ofile[uap->i] = NULL; 259 *pf = 0; 260 } 261 262 fstat() 263 { 264 register struct file *fp; 265 register struct a { 266 int fdes; 267 struct stat *sb; 268 } *uap; 269 struct stat ub; 270 271 uap = (struct a *)u.u_ap; 272 fp = getf(uap->fdes); 273 if (fp == 0) 274 return; 275 switch (fp->f_type) { 276 277 case DTYPE_INODE: 278 u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 279 break; 280 281 case DTYPE_SOCKET: 282 u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 283 break; 284 285 default: 286 panic("fstat"); 287 /*NOTREACHED*/ 288 } 289 if (u.u_error == 0) 290 u.u_error = copyout(&ub, uap->sb, sizeof (ub)); 291 } 292 293 /* 294 * Allocate a user file descriptor. 295 */ 296 ufalloc(i) 297 register int i; 298 { 299 300 for (; i < NOFILE; i++) 301 if (u.u_ofile[i] == NULL) { 302 u.u_r.r_val1 = i; 303 u.u_pofile[i] = 0; 304 return (i); 305 } 306 u.u_error = EMFILE; 307 return (-1); 308 } 309 310 ufavail() 311 { 312 register int i, avail = 0; 313 314 for (i = 0; i < NOFILE; i++) 315 if (u.u_ofile[i] == NULL) 316 avail++; 317 return (avail); 318 } 319 320 struct file *lastf; 321 /* 322 * Allocate a user file descriptor 323 * and a file structure. 324 * Initialize the descriptor 325 * to point at the file structure. 326 */ 327 struct file * 328 falloc() 329 { 330 register struct file *fp; 331 register i; 332 333 i = ufalloc(0); 334 if (i < 0) 335 return (NULL); 336 if (lastf == 0) 337 lastf = file; 338 for (fp = lastf; fp < fileNFILE; fp++) 339 if (fp->f_count == 0) 340 goto slot; 341 for (fp = file; fp < lastf; fp++) 342 if (fp->f_count == 0) 343 goto slot; 344 tablefull("file"); 345 u.u_error = ENFILE; 346 return (NULL); 347 slot: 348 u.u_ofile[i] = fp; 349 fp->f_count = 1; 350 fp->f_data = 0; 351 fp->f_offset = 0; 352 lastf = fp + 1; 353 return (fp); 354 } 355 356 /* 357 * Convert a user supplied file descriptor into a pointer 358 * to a file structure. Only task is to check range of the descriptor. 359 * Critical paths should use the GETF macro. 360 */ 361 struct file * 362 getf(f) 363 register int f; 364 { 365 register struct file *fp; 366 367 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 368 u.u_error = EBADF; 369 return (NULL); 370 } 371 return (fp); 372 } 373 374 /* 375 * Internal form of close. 376 * Decrement reference count on file structure. 377 * If last reference not going away, but no more 378 * references except in message queues, run a 379 * garbage collect. This would better be done by 380 * forcing a gc() to happen sometime soon, rather 381 * than running one each time. 382 */ 383 closef(fp) 384 register struct file *fp; 385 { 386 387 if (fp == NULL) 388 return; 389 if (fp->f_count > 1) { 390 fp->f_count--; 391 if (fp->f_count == fp->f_msgcount) 392 unp_gc(); 393 return; 394 } 395 (*fp->f_ops->fo_close)(fp); 396 fp->f_count = 0; 397 } 398 399 /* 400 * Apply an advisory lock on a file descriptor. 401 */ 402 flock() 403 { 404 register struct a { 405 int fd; 406 int how; 407 } *uap = (struct a *)u.u_ap; 408 register struct file *fp; 409 register u_char *pf; 410 int cmd; 411 412 fp = getf(uap->fd); 413 if (fp == NULL) 414 return; 415 cmd = uap->how; 416 pf = (u_char *)&u.u_pofile[uap->fd]; 417 if (cmd & LOCK_UN) { 418 unlockf(fp, pf); 419 return; 420 } 421 /* 422 * No reason to write lock a file we've already 423 * write locked, similarly with a read lock. 424 */ 425 if ((*pf & UF_EXLOCK) && (cmd & LOCK_EX) || 426 (*pf & UF_SHLOCK) && (cmd & LOCK_SH)) 427 return; 428 switch (fp->f_type) { 429 430 case DTYPE_INODE: 431 u.u_error = ino_lock((struct inode *)fp->f_data, pf, cmd); 432 break; 433 434 case DTYPE_SOCKET: 435 u.u_error = soo_lock((struct socket *)fp->f_data, pf, cmd); 436 break; 437 438 default: 439 panic("lockf"); 440 } 441 } 442 443 unlockf(fp, pf) 444 register struct file *fp; 445 register u_char *pf; 446 { 447 448 if ((*pf & (UF_SHLOCK|UF_EXLOCK)) == 0) 449 return; 450 switch (fp->f_type) { 451 452 case DTYPE_INODE: 453 ino_unlock((struct inode *)fp->f_data, *pf); 454 break; 455 456 case DTYPE_SOCKET: 457 soo_unlock((struct socket *)fp->f_data, *pf); 458 break; 459 460 default: 461 panic("unlockf"); 462 } 463 *pf &= ~(UF_SHLOCK|UF_EXLOCK); 464 } 465