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