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