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