1 /* kern_descrip.c 6.5 84/08/29 */ 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 "conf.h" 11 #include "file.h" 12 #include "socket.h" 13 #include "socketvar.h" 14 #include "mount.h" 15 #include "stat.h" 16 17 #include "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 GETF(fp, uap->i); 59 j = ufalloc(0); 60 if (j < 0) 61 return; 62 dupit(j, fp, u.u_pofile[uap->i]); 63 } 64 65 dup2() 66 { 67 register struct a { 68 int i, j; 69 } *uap = (struct a *) u.u_ap; 70 register struct file *fp; 71 72 GETF(fp, uap->i); 73 if (uap->j < 0 || uap->j >= NOFILE) { 74 u.u_error = EBADF; 75 return; 76 } 77 u.u_r.r_val1 = uap->j; 78 if (uap->i == uap->j) 79 return; 80 if (u.u_ofile[uap->j]) { 81 if (u.u_pofile[uap->j] & UF_MAPPED) 82 munmapfd(uap->j); 83 closef(u.u_ofile[uap->j]); 84 if (u.u_error) 85 return; 86 } 87 dupit(uap->j, fp, u.u_pofile[uap->i]); 88 } 89 90 dupit(fd, fp, flags) 91 int fd; 92 register struct file *fp; 93 register int flags; 94 { 95 96 u.u_ofile[fd] = fp; 97 u.u_pofile[fd] = flags; 98 fp->f_count++; 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); 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 register struct a { 229 int i; 230 } *uap = (struct a *)u.u_ap; 231 register struct file *fp; 232 register u_char *pf; 233 234 GETF(fp, uap->i); 235 pf = (u_char *)&u.u_pofile[uap->i]; 236 if (*pf & UF_MAPPED) 237 munmapfd(uap->i); 238 u.u_ofile[uap->i] = NULL; 239 *pf = 0; 240 closef(fp); 241 /* WHAT IF u.u_error ? */ 242 } 243 244 fstat() 245 { 246 register struct file *fp; 247 register struct a { 248 int fdes; 249 struct stat *sb; 250 } *uap; 251 struct stat ub; 252 253 uap = (struct a *)u.u_ap; 254 GETF(fp, uap->fdes); 255 switch (fp->f_type) { 256 257 case DTYPE_INODE: 258 u.u_error = ino_stat((struct inode *)fp->f_data, &ub); 259 break; 260 261 case DTYPE_SOCKET: 262 u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 263 break; 264 265 default: 266 panic("fstat"); 267 /*NOTREACHED*/ 268 } 269 if (u.u_error == 0) 270 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 271 sizeof (ub)); 272 } 273 274 /* 275 * Allocate a user file descriptor. 276 */ 277 ufalloc(i) 278 register int i; 279 { 280 281 for (; i < NOFILE; i++) 282 if (u.u_ofile[i] == NULL) { 283 u.u_r.r_val1 = i; 284 u.u_pofile[i] = 0; 285 return (i); 286 } 287 u.u_error = EMFILE; 288 return (-1); 289 } 290 291 ufavail() 292 { 293 register int i, avail = 0; 294 295 for (i = 0; i < NOFILE; i++) 296 if (u.u_ofile[i] == NULL) 297 avail++; 298 return (avail); 299 } 300 301 struct file *lastf; 302 /* 303 * Allocate a user file descriptor 304 * and a file structure. 305 * Initialize the descriptor 306 * to point at the file structure. 307 */ 308 struct file * 309 falloc() 310 { 311 register struct file *fp; 312 register i; 313 314 i = ufalloc(0); 315 if (i < 0) 316 return (NULL); 317 if (lastf == 0) 318 lastf = file; 319 for (fp = lastf; fp < fileNFILE; fp++) 320 if (fp->f_count == 0) 321 goto slot; 322 for (fp = file; fp < lastf; fp++) 323 if (fp->f_count == 0) 324 goto slot; 325 tablefull("file"); 326 u.u_error = ENFILE; 327 return (NULL); 328 slot: 329 u.u_ofile[i] = fp; 330 fp->f_count = 1; 331 fp->f_data = 0; 332 fp->f_offset = 0; 333 lastf = fp + 1; 334 return (fp); 335 } 336 337 /* 338 * Convert a user supplied file descriptor into a pointer 339 * to a file structure. Only task is to check range of the descriptor. 340 * Critical paths should use the GETF macro. 341 */ 342 struct file * 343 getf(f) 344 register int f; 345 { 346 register struct file *fp; 347 348 if ((unsigned)f >= NOFILE || (fp = u.u_ofile[f]) == NULL) { 349 u.u_error = EBADF; 350 return (NULL); 351 } 352 return (fp); 353 } 354 355 /* 356 * Internal form of close. 357 * Decrement reference count on file structure. 358 * If last reference not going away, but no more 359 * references except in message queues, run a 360 * garbage collect. This would better be done by 361 * forcing a gc() to happen sometime soon, rather 362 * than running one each time. 363 */ 364 closef(fp) 365 register struct file *fp; 366 { 367 368 if (fp == NULL) 369 return; 370 if (fp->f_count > 1) { 371 fp->f_count--; 372 if (fp->f_count == fp->f_msgcount) 373 unp_gc(); 374 return; 375 } 376 (*fp->f_ops->fo_close)(fp); 377 fp->f_count = 0; 378 } 379 380 /* 381 * Apply an advisory lock on a file descriptor. 382 */ 383 flock() 384 { 385 register struct a { 386 int fd; 387 int how; 388 } *uap = (struct a *)u.u_ap; 389 register struct file *fp; 390 391 GETF(fp, uap->fd); 392 if (fp->f_type != DTYPE_INODE) { 393 u.u_error = EOPNOTSUPP; 394 return; 395 } 396 if (uap->how & LOCK_UN) { 397 ino_unlock(fp, FSHLOCK|FEXLOCK); 398 return; 399 } 400 /* avoid work... */ 401 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 402 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 403 return; 404 u.u_error = ino_lock(fp, uap->how); 405 } 406