1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)kern_descrip.c 7.4 (Berkeley) 05/09/89 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "syscontext.h" 23 #include "kernel.h" 24 #include "vnode.h" 25 #include "proc.h" 26 #include "file.h" 27 #include "socket.h" 28 #include "socketvar.h" 29 #include "mount.h" 30 #include "stat.h" 31 32 #include "ioctl.h" 33 34 /* 35 * Descriptor management. 36 */ 37 38 /* 39 * System calls on descriptors. 40 */ 41 getdtablesize() 42 { 43 44 u.u_r.r_val1 = NOFILE; 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 if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 58 RETURN (EBADF); 59 if (u.u_error = ufalloc(0, &j)) 60 return; 61 u.u_r.r_val1 = j; 62 dupit(j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 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 if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) 73 RETURN (EBADF); 74 if (uap->j < 0 || uap->j >= NOFILE) { 75 u.u_error = EBADF; 76 return; 77 } 78 u.u_r.r_val1 = uap->j; 79 if (uap->i == uap->j) 80 return; 81 if (u.u_ofile[uap->j]) { 82 if (u.u_pofile[uap->j] & UF_MAPPED) 83 munmapfd(uap->j); 84 closef(u.u_ofile[uap->j]); 85 if (u.u_error) 86 return; 87 } 88 dupit(uap->j, fp, u.u_pofile[uap->i] &~ UF_EXCLOSE); 89 } 90 91 dupit(fd, fp, flags) 92 int fd; 93 register struct file *fp; 94 register int flags; 95 { 96 97 u.u_ofile[fd] = fp; 98 u.u_pofile[fd] = flags; 99 fp->f_count++; 100 if (fd > u.u_lastfile) 101 u.u_lastfile = fd; 102 } 103 104 /* 105 * The file control system call. 106 */ 107 fcntl() 108 { 109 register struct file *fp; 110 register struct a { 111 int fdes; 112 int cmd; 113 int arg; 114 } *uap = (struct a *)u.u_ap; 115 register char *pop; 116 int i; 117 118 if ((unsigned)uap->fdes >= NOFILE || 119 (fp = u.u_ofile[uap->fdes]) == NULL) 120 RETURN (EBADF); 121 pop = &u.u_pofile[uap->fdes]; 122 switch(uap->cmd) { 123 case F_DUPFD: 124 if (uap->arg < 0 || uap->arg >= NOFILE) { 125 u.u_error = EINVAL; 126 return; 127 } 128 if (u.u_error = ufalloc(uap->arg, &i)) 129 return; 130 u.u_r.r_val1 = i; 131 dupit(i, fp, *pop &~ UF_EXCLOSE); 132 break; 133 134 case F_GETFD: 135 u.u_r.r_val1 = *pop & 1; 136 break; 137 138 case F_SETFD: 139 *pop = (*pop &~ 1) | (uap->arg & 1); 140 break; 141 142 case F_GETFL: 143 u.u_r.r_val1 = fp->f_flag+FOPEN; 144 break; 145 146 case F_SETFL: 147 fp->f_flag &= FCNTLCANT; 148 fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; 149 u.u_error = fset(fp, FNDELAY, fp->f_flag & FNDELAY); 150 if (u.u_error) 151 break; 152 u.u_error = fset(fp, FASYNC, fp->f_flag & FASYNC); 153 if (u.u_error) 154 (void) fset(fp, FNDELAY, 0); 155 break; 156 157 case F_GETOWN: 158 u.u_error = fgetown(fp, &u.u_r.r_val1); 159 break; 160 161 case F_SETOWN: 162 u.u_error = fsetown(fp, uap->arg); 163 break; 164 165 default: 166 u.u_error = EINVAL; 167 } 168 } 169 170 fset(fp, bit, value) 171 struct file *fp; 172 int bit, value; 173 { 174 175 if (value) 176 fp->f_flag |= bit; 177 else 178 fp->f_flag &= ~bit; 179 return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), 180 (caddr_t)&value)); 181 } 182 183 fgetown(fp, valuep) 184 struct file *fp; 185 int *valuep; 186 { 187 int error; 188 189 switch (fp->f_type) { 190 191 case DTYPE_SOCKET: 192 *valuep = ((struct socket *)fp->f_data)->so_pgid; 193 return (0); 194 195 default: 196 error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); 197 *valuep = -*valuep; 198 return (error); 199 } 200 } 201 202 fsetown(fp, value) 203 struct file *fp; 204 int value; 205 { 206 207 if (fp->f_type == DTYPE_SOCKET) { 208 ((struct socket *)fp->f_data)->so_pgid = value; 209 return (0); 210 } 211 if (value > 0) { 212 struct proc *p = pfind(value); 213 if (p == 0) 214 return (ESRCH); 215 value = p->p_pgrp->pg_id; 216 } else 217 value = -value; 218 return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); 219 } 220 221 fioctl(fp, cmd, value) 222 struct file *fp; 223 int cmd; 224 caddr_t value; 225 { 226 227 return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); 228 } 229 230 close() 231 { 232 struct a { 233 int fdes; 234 } *uap = (struct a *)u.u_ap; 235 register struct file *fp; 236 register u_char *pf; 237 238 if ((unsigned)uap->fdes >= NOFILE || 239 (fp = u.u_ofile[uap->fdes]) == NULL) 240 RETURN (EBADF); 241 pf = (u_char *)&u.u_pofile[uap->fdes]; 242 if (*pf & UF_MAPPED) 243 munmapfd(uap->fdes); 244 u.u_ofile[uap->fdes] = NULL; 245 while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) 246 u.u_lastfile--; 247 *pf = 0; 248 closef(fp); 249 /* WHAT IF u.u_error ? */ 250 } 251 252 fstat() 253 { 254 register struct file *fp; 255 register struct a { 256 int fdes; 257 struct stat *sb; 258 } *uap = (struct a *)u.u_ap; 259 struct stat ub; 260 261 if ((unsigned)uap->fdes >= NOFILE || 262 (fp = u.u_ofile[uap->fdes]) == NULL) 263 RETURN (EBADF); 264 switch (fp->f_type) { 265 266 case DTYPE_VNODE: 267 u.u_error = vn_stat((struct vnode *)fp->f_data, &ub); 268 break; 269 270 case DTYPE_SOCKET: 271 u.u_error = soo_stat((struct socket *)fp->f_data, &ub); 272 break; 273 274 default: 275 panic("fstat"); 276 /*NOTREACHED*/ 277 } 278 if (u.u_error == 0) 279 u.u_error = copyout((caddr_t)&ub, (caddr_t)uap->sb, 280 sizeof (ub)); 281 } 282 283 /* 284 * Allocate a user file descriptor. 285 */ 286 ufalloc(want, result) 287 register int want; 288 int *result; 289 { 290 291 for (; want < NOFILE; want++) 292 if (u.u_ofile[want] == NULL) { 293 u.u_pofile[want] = 0; 294 if (want > u.u_lastfile) 295 u.u_lastfile = want; 296 if (result) 297 *result = want; 298 return (0); 299 } 300 return (EMFILE); 301 } 302 303 ufavail() 304 { 305 register int i, avail = 0; 306 307 for (i = 0; i < NOFILE; i++) 308 if (u.u_ofile[i] == NULL) 309 avail++; 310 return (avail); 311 } 312 313 struct file *lastf; 314 /* 315 * Allocate a user file descriptor 316 * and a file structure. 317 * Initialize the descriptor 318 * to point at the file structure. 319 */ 320 falloc(resultfp, resultfd) 321 struct file **resultfp; 322 int *resultfd; 323 { 324 register struct file *fp; 325 int error, i; 326 327 if (error = ufalloc(0, &i)) 328 return (error); 329 if (lastf == 0) 330 lastf = file; 331 for (fp = lastf; fp < fileNFILE; fp++) 332 if (fp->f_count == 0) 333 goto slot; 334 for (fp = file; fp < lastf; fp++) 335 if (fp->f_count == 0) 336 goto slot; 337 tablefull("file"); 338 return (ENFILE); 339 slot: 340 u.u_ofile[i] = fp; 341 fp->f_count = 1; 342 fp->f_data = 0; 343 fp->f_offset = 0; 344 fp->f_cred = u.u_cred; 345 crhold(fp->f_cred); 346 lastf = fp + 1; 347 if (resultfp) 348 *resultfp = fp; 349 if (resultfd) 350 *resultfd = i; 351 return (0); 352 } 353 354 /* 355 * Internal form of close. 356 * Decrement reference count on file structure. 357 */ 358 closef(fp) 359 register struct file *fp; 360 { 361 362 if (fp == NULL) 363 return; 364 if (fp->f_count > 1) { 365 fp->f_count--; 366 return; 367 } 368 if (fp->f_count < 1) 369 panic("closef: count < 1"); 370 (*fp->f_ops->fo_close)(fp); 371 crfree(fp->f_cred); 372 fp->f_count = 0; 373 } 374 375 /* 376 * Apply an advisory lock on a file descriptor. 377 */ 378 flock() 379 { 380 register struct a { 381 int fdes; 382 int how; 383 } *uap = (struct a *)u.u_ap; 384 register struct file *fp; 385 386 if ((unsigned)uap->fdes >= NOFILE || 387 (fp = u.u_ofile[uap->fdes]) == NULL) 388 RETURN (EBADF); 389 if (fp->f_type != DTYPE_VNODE) { 390 u.u_error = EOPNOTSUPP; 391 return; 392 } 393 if (uap->how & LOCK_UN) { 394 vn_unlock(fp, FSHLOCK|FEXLOCK); 395 return; 396 } 397 if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) 398 return; /* error? */ 399 if (uap->how & LOCK_EX) 400 uap->how &= ~LOCK_SH; 401 /* avoid work... */ 402 if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || 403 (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) 404 return; 405 u.u_error = vn_lock(fp, uap->how); 406 } 407 408 /* 409 * File Descriptor pseudo-device driver (/dev/fd/). 410 * 411 * Fred Blonder - U of Maryland 11-Sep-1984 412 * 413 * Opening minor device N dup()s the file (if any) connected to file 414 * descriptor N belonging to the calling process. Note that this driver 415 * consists of only the ``open()'' routine, because all subsequent 416 * references to this file will be direct to the other driver. 417 */ 418 /* ARGSUSED */ 419 fdopen(dev, mode, type) 420 dev_t dev; 421 int mode, type; 422 { 423 struct file *fp, *wfp; 424 int indx, dfd, rwmode; 425 426 /* 427 * Note the horrid kludge here: u.u_r.r_val1 contains the value 428 * of the new file descriptor, which was set before the call to 429 * vn_open() by copen() in vfs_syscalls.c 430 */ 431 indx = u.u_r.r_val1; /* XXX */ 432 if ((unsigned)indx >= NOFILE || (fp = u.u_ofile[indx]) == NULL) 433 return (EBADF); 434 dfd = minor(dev); 435 if ((unsigned)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL) 436 return (EBADF); 437 /* 438 * We must explicitly test for this case because ufalloc() may 439 * have allocated us the same file desriptor we are referring 440 * to, if the proccess referred to an invalid (closed) descriptor. 441 * Ordinarily this would be caught by the check for NULL above, 442 * but by the time we reach this routine u_pofile[minor(dev)] 443 * could already be set to point to our file struct. 444 */ 445 if (fp == wfp) 446 return (EBADF); 447 /* 448 * Fake a ``dup()'' sys call. 449 * Check that the mode the file is being opened 450 * for is consistent with the mode of the existing 451 * descriptor. This isn't as clean as it should be, 452 * but this entire driver is a real kludge anyway. 453 */ 454 rwmode = mode & (FREAD|FWRITE); 455 if ((fp->f_flag & rwmode) != rwmode) 456 return (EACCES); 457 /* 458 * Delete references to this pseudo-device. 459 * Note that fp->f_count is guaranteed == 1, and 460 * that fp references the vnode for this driver. 461 */ 462 if (fp->f_count != 1 || fp->f_type != DTYPE_VNODE) 463 panic("fdopen"); 464 vrele((struct vnode *)fp->f_data); 465 fp->f_count = 0; 466 /* 467 * Dup the file descriptor. 468 */ 469 dupit(indx, wfp, u.u_pofile[dfd]); 470 return (0); 471 } 472