|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)kern_descrip.c 7.16 (Berkeley) 6/28/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "systm.h" ! 25: #include "user.h" ! 26: #include "kernel.h" ! 27: #include "vnode.h" ! 28: #include "proc.h" ! 29: #include "file.h" ! 30: #include "socket.h" ! 31: #include "socketvar.h" ! 32: #include "stat.h" ! 33: #include "ioctl.h" ! 34: ! 35: /* ! 36: * Descriptor management. ! 37: */ ! 38: ! 39: /* ! 40: * System calls on descriptors. ! 41: */ ! 42: /* ARGSUSED */ ! 43: getdtablesize(p, uap, retval) ! 44: struct proc *p; ! 45: struct args *uap; ! 46: int *retval; ! 47: { ! 48: ! 49: *retval = NOFILE; ! 50: return (0); ! 51: } ! 52: ! 53: /* ! 54: * Duplicate a file descriptor. ! 55: */ ! 56: /* ARGSUSED */ ! 57: dup(p, uap, retval) ! 58: struct proc *p; ! 59: struct args { ! 60: int i; ! 61: } *uap; ! 62: int *retval; ! 63: { ! 64: struct file *fp; ! 65: int fd, error; ! 66: ! 67: /* ! 68: * XXX Compatibility ! 69: */ ! 70: if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); } ! 71: ! 72: if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) ! 73: return (EBADF); ! 74: if (error = ufalloc(0, &fd)) ! 75: return (error); ! 76: u.u_ofile[fd] = fp; ! 77: u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE; ! 78: fp->f_count++; ! 79: if (fd > u.u_lastfile) ! 80: u.u_lastfile = fd; ! 81: *retval = fd; ! 82: return (0); ! 83: } ! 84: ! 85: /* ! 86: * Duplicate a file descriptor to a particular value. ! 87: */ ! 88: /* ARGSUSED */ ! 89: dup2(p, uap, retval) ! 90: struct proc *p; ! 91: register struct args { ! 92: int i; ! 93: int j; ! 94: } *uap; ! 95: int *retval; ! 96: { ! 97: register struct file *fp; ! 98: int error; ! 99: ! 100: if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL) ! 101: return (EBADF); ! 102: if (uap->j < 0 || uap->j >= NOFILE) ! 103: return (EBADF); ! 104: *retval = uap->j; ! 105: if (uap->i == uap->j) ! 106: return (0); ! 107: if (u.u_ofile[uap->j]) { ! 108: if (u.u_pofile[uap->j] & UF_MAPPED) ! 109: munmapfd(uap->j); ! 110: error = closef(u.u_ofile[uap->j]); ! 111: } ! 112: u.u_ofile[uap->j] = fp; ! 113: u.u_pofile[uap->j] = u.u_pofile[uap->i] &~ UF_EXCLOSE; ! 114: fp->f_count++; ! 115: if (uap->j > u.u_lastfile) ! 116: u.u_lastfile = uap->j; ! 117: /* ! 118: * dup2() must suceed even though the close had an error. ! 119: */ ! 120: error = 0; /* XXX */ ! 121: return (error); ! 122: } ! 123: ! 124: /* ! 125: * The file control system call. ! 126: */ ! 127: /* ARGSUSED */ ! 128: fcntl(p, uap, retval) ! 129: struct proc *p; ! 130: register struct args { ! 131: int fdes; ! 132: int cmd; ! 133: int arg; ! 134: } *uap; ! 135: int *retval; ! 136: { ! 137: register struct file *fp; ! 138: register char *pop; ! 139: int i, error; ! 140: ! 141: if ((unsigned)uap->fdes >= NOFILE || ! 142: (fp = u.u_ofile[uap->fdes]) == NULL) ! 143: return (EBADF); ! 144: pop = &u.u_pofile[uap->fdes]; ! 145: switch(uap->cmd) { ! 146: case F_DUPFD: ! 147: if (uap->arg < 0 || uap->arg >= NOFILE) ! 148: return (EINVAL); ! 149: if (error = ufalloc(uap->arg, &i)) ! 150: return (error); ! 151: u.u_ofile[i] = fp; ! 152: u.u_pofile[i] = *pop &~ UF_EXCLOSE; ! 153: fp->f_count++; ! 154: if (i > u.u_lastfile) ! 155: u.u_lastfile = i; ! 156: *retval = i; ! 157: return (0); ! 158: ! 159: case F_GETFD: ! 160: *retval = *pop & 1; ! 161: return (0); ! 162: ! 163: case F_SETFD: ! 164: *pop = (*pop &~ 1) | (uap->arg & 1); ! 165: return (0); ! 166: ! 167: case F_GETFL: ! 168: *retval = fp->f_flag + FOPEN; ! 169: return (0); ! 170: ! 171: case F_SETFL: ! 172: fp->f_flag &= FCNTLCANT; ! 173: fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT; ! 174: if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY)) ! 175: return (error); ! 176: if (error = fset(fp, FASYNC, fp->f_flag & FASYNC)) ! 177: (void) fset(fp, FNDELAY, 0); ! 178: return (error); ! 179: ! 180: case F_GETOWN: ! 181: return (fgetown(fp, retval)); ! 182: ! 183: case F_SETOWN: ! 184: return (fsetown(fp, uap->arg)); ! 185: ! 186: default: ! 187: return (EINVAL); ! 188: } ! 189: /* NOTREACHED */ ! 190: } ! 191: ! 192: fset(fp, bit, value) ! 193: struct file *fp; ! 194: int bit, value; ! 195: { ! 196: ! 197: if (value) ! 198: fp->f_flag |= bit; ! 199: else ! 200: fp->f_flag &= ~bit; ! 201: return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC), ! 202: (caddr_t)&value)); ! 203: } ! 204: ! 205: fgetown(fp, valuep) ! 206: struct file *fp; ! 207: int *valuep; ! 208: { ! 209: int error; ! 210: ! 211: switch (fp->f_type) { ! 212: ! 213: case DTYPE_SOCKET: ! 214: *valuep = ((struct socket *)fp->f_data)->so_pgid; ! 215: return (0); ! 216: ! 217: default: ! 218: error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep); ! 219: *valuep = -*valuep; ! 220: return (error); ! 221: } ! 222: } ! 223: ! 224: fsetown(fp, value) ! 225: struct file *fp; ! 226: int value; ! 227: { ! 228: ! 229: if (fp->f_type == DTYPE_SOCKET) { ! 230: ((struct socket *)fp->f_data)->so_pgid = value; ! 231: return (0); ! 232: } ! 233: if (value > 0) { ! 234: struct proc *p = pfind(value); ! 235: if (p == 0) ! 236: return (ESRCH); ! 237: value = p->p_pgrp->pg_id; ! 238: } else ! 239: value = -value; ! 240: return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value)); ! 241: } ! 242: ! 243: fioctl(fp, cmd, value) ! 244: struct file *fp; ! 245: int cmd; ! 246: caddr_t value; ! 247: { ! 248: ! 249: return ((*fp->f_ops->fo_ioctl)(fp, cmd, value)); ! 250: } ! 251: ! 252: /* ! 253: * Close a file descriptor. ! 254: */ ! 255: /* ARGSUSED */ ! 256: close(p, uap, retval) ! 257: struct proc *p; ! 258: struct args { ! 259: int fdes; ! 260: } *uap; ! 261: int *retval; ! 262: { ! 263: register struct file *fp; ! 264: register u_char *pf; ! 265: ! 266: if ((unsigned)uap->fdes >= NOFILE || ! 267: (fp = u.u_ofile[uap->fdes]) == NULL) ! 268: return (EBADF); ! 269: pf = (u_char *)&u.u_pofile[uap->fdes]; ! 270: if (*pf & UF_MAPPED) ! 271: munmapfd(uap->fdes); ! 272: u.u_ofile[uap->fdes] = NULL; ! 273: while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL) ! 274: u.u_lastfile--; ! 275: *pf = 0; ! 276: return (closef(fp)); ! 277: } ! 278: ! 279: /* ! 280: * Return status information about a file descriptor. ! 281: */ ! 282: /* ARGSUSED */ ! 283: fstat(p, uap, retval) ! 284: struct proc *p; ! 285: register struct args { ! 286: int fdes; ! 287: struct stat *sb; ! 288: } *uap; ! 289: int *retval; ! 290: { ! 291: register struct file *fp; ! 292: struct stat ub; ! 293: int error; ! 294: ! 295: if ((unsigned)uap->fdes >= NOFILE || ! 296: (fp = u.u_ofile[uap->fdes]) == NULL) ! 297: return (EBADF); ! 298: switch (fp->f_type) { ! 299: ! 300: case DTYPE_VNODE: ! 301: error = vn_stat((struct vnode *)fp->f_data, &ub); ! 302: break; ! 303: ! 304: case DTYPE_SOCKET: ! 305: error = soo_stat((struct socket *)fp->f_data, &ub); ! 306: break; ! 307: ! 308: default: ! 309: panic("fstat"); ! 310: /*NOTREACHED*/ ! 311: } ! 312: if (error == 0) ! 313: error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); ! 314: return (error); ! 315: } ! 316: ! 317: /* ! 318: * Allocate a user file descriptor. ! 319: */ ! 320: ufalloc(want, result) ! 321: register int want; ! 322: int *result; ! 323: { ! 324: ! 325: for (; want < NOFILE; want++) { ! 326: if (u.u_ofile[want] == NULL) { ! 327: u.u_pofile[want] = 0; ! 328: if (want > u.u_lastfile) ! 329: u.u_lastfile = want; ! 330: *result = want; ! 331: return (0); ! 332: } ! 333: } ! 334: return (EMFILE); ! 335: } ! 336: ! 337: /* ! 338: * Check to see if any user file descriptors are available. ! 339: */ ! 340: ufavail() ! 341: { ! 342: register int i, avail = 0; ! 343: ! 344: for (i = 0; i < NOFILE; i++) ! 345: if (u.u_ofile[i] == NULL) ! 346: avail++; ! 347: return (avail); ! 348: } ! 349: ! 350: struct file *lastf; ! 351: /* ! 352: * Allocate a user file descriptor ! 353: * and a file structure. ! 354: * Initialize the descriptor ! 355: * to point at the file structure. ! 356: */ ! 357: falloc(resultfp, resultfd) ! 358: struct file **resultfp; ! 359: int *resultfd; ! 360: { ! 361: register struct file *fp; ! 362: int error, i; ! 363: ! 364: if (error = ufalloc(0, &i)) ! 365: return (error); ! 366: if (lastf == 0) ! 367: lastf = file; ! 368: for (fp = lastf; fp < fileNFILE; fp++) ! 369: if (fp->f_count == 0) ! 370: goto slot; ! 371: for (fp = file; fp < lastf; fp++) ! 372: if (fp->f_count == 0) ! 373: goto slot; ! 374: tablefull("file"); ! 375: return (ENFILE); ! 376: slot: ! 377: u.u_ofile[i] = fp; ! 378: fp->f_count = 1; ! 379: fp->f_data = 0; ! 380: fp->f_offset = 0; ! 381: fp->f_cred = u.u_cred; ! 382: crhold(fp->f_cred); ! 383: lastf = fp + 1; ! 384: if (resultfp) ! 385: *resultfp = fp; ! 386: if (resultfd) ! 387: *resultfd = i; ! 388: return (0); ! 389: } ! 390: ! 391: /* ! 392: * Internal form of close. ! 393: * Decrement reference count on file structure. ! 394: */ ! 395: closef(fp) ! 396: register struct file *fp; ! 397: { ! 398: int error; ! 399: ! 400: if (fp == NULL) ! 401: return (0); ! 402: if (fp->f_count > 1) { ! 403: fp->f_count--; ! 404: return (0); ! 405: } ! 406: if (fp->f_count < 1) ! 407: panic("closef: count < 1"); ! 408: error = (*fp->f_ops->fo_close)(fp); ! 409: crfree(fp->f_cred); ! 410: fp->f_count = 0; ! 411: return (error); ! 412: } ! 413: ! 414: /* ! 415: * Apply an advisory lock on a file descriptor. ! 416: */ ! 417: /* ARGSUSED */ ! 418: flock(p, uap, retval) ! 419: struct proc *p; ! 420: register struct args { ! 421: int fdes; ! 422: int how; ! 423: } *uap; ! 424: int *retval; ! 425: { ! 426: register struct file *fp; ! 427: ! 428: if ((unsigned)uap->fdes >= NOFILE || ! 429: (fp = u.u_ofile[uap->fdes]) == NULL) ! 430: return (EBADF); ! 431: if (fp->f_type != DTYPE_VNODE) ! 432: return (EOPNOTSUPP); ! 433: if (uap->how & LOCK_UN) { ! 434: vn_unlock(fp, FSHLOCK|FEXLOCK); ! 435: return (0); ! 436: } ! 437: if ((uap->how & (LOCK_SH | LOCK_EX)) == 0) ! 438: return (0); /* error? */ ! 439: if (uap->how & LOCK_EX) ! 440: uap->how &= ~LOCK_SH; ! 441: /* avoid work... */ ! 442: if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) || ! 443: (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH)) ! 444: return (0); ! 445: return (vn_lock(fp, uap->how)); ! 446: } ! 447: ! 448: /* ! 449: * File Descriptor pseudo-device driver (/dev/fd/). ! 450: * ! 451: * Opening minor device N dup()s the file (if any) connected to file ! 452: * descriptor N belonging to the calling process. Note that this driver ! 453: * consists of only the ``open()'' routine, because all subsequent ! 454: * references to this file will be direct to the other driver. ! 455: */ ! 456: /* ARGSUSED */ ! 457: fdopen(dev, mode, type) ! 458: dev_t dev; ! 459: int mode, type; ! 460: { ! 461: struct proc *p = u.u_procp; /* XXX */ ! 462: ! 463: /* ! 464: * XXX Kludge: set p->p_dupfd to contain the value of the ! 465: * the file descriptor being sought for duplication. The error ! 466: * return ensures that the vnode for this device will be released ! 467: * by vn_open. Open will detect this special error and take the ! 468: * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN ! 469: * will simply report the error. ! 470: */ ! 471: p->p_dupfd = minor(dev); ! 472: return (ENODEV); ! 473: } ! 474: ! 475: /* ! 476: * Duplicate the specified descriptor to a free descriptor. ! 477: */ ! 478: dupfdopen(indx, dfd, mode) ! 479: register int indx, dfd; ! 480: int mode; ! 481: { ! 482: register struct file *wfp; ! 483: struct file *fp; ! 484: ! 485: /* ! 486: * If the to-be-dup'd fd number is greater than the allowed number ! 487: * of file descriptors, or the fd to be dup'd has already been ! 488: * closed, reject. Note, check for new == old is necessary as ! 489: * falloc could allocate an already closed to-be-dup'd descriptor ! 490: * as the new descriptor. ! 491: */ ! 492: fp = u.u_ofile[indx]; ! 493: if ((u_int)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL || ! 494: fp == wfp) ! 495: return (EBADF); ! 496: ! 497: /* ! 498: * Check that the mode the file is being opened for is a subset ! 499: * of the mode of the existing descriptor. ! 500: */ ! 501: if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) ! 502: return (EACCES); ! 503: u.u_ofile[indx] = wfp; ! 504: u.u_pofile[indx] = u.u_pofile[dfd]; ! 505: wfp->f_count++; ! 506: if (indx > u.u_lastfile) ! 507: u.u_lastfile = indx; ! 508: return (0); ! 509: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.