|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)kern_descrip.c 7.28 (Berkeley) 6/25/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "filedesc.h" ! 39: #include "kernel.h" ! 40: #include "vnode.h" ! 41: #include "proc.h" ! 42: #include "file.h" ! 43: #include "socket.h" ! 44: #include "socketvar.h" ! 45: #include "stat.h" ! 46: #include "ioctl.h" ! 47: #include "fcntl.h" ! 48: #include "malloc.h" ! 49: #include "syslog.h" ! 50: #include "resourcevar.h" ! 51: ! 52: /* ! 53: * Descriptor management. ! 54: */ ! 55: struct file *filehead; /* head of list of open files */ ! 56: int nfiles; /* actual number of open files */ ! 57: ! 58: /* ! 59: * System calls on descriptors. ! 60: */ ! 61: /* ARGSUSED */ ! 62: getdtablesize(p, uap, retval) ! 63: struct proc *p; ! 64: struct args *uap; ! 65: int *retval; ! 66: { ! 67: ! 68: *retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur; ! 69: return (0); ! 70: } ! 71: ! 72: /* ! 73: * Duplicate a file descriptor. ! 74: */ ! 75: /* ARGSUSED */ ! 76: dup(p, uap, retval) ! 77: struct proc *p; ! 78: struct args { ! 79: int i; ! 80: } *uap; ! 81: int *retval; ! 82: { ! 83: register struct filedesc *fdp = p->p_fd; ! 84: struct file *fp; ! 85: int fd, error; ! 86: ! 87: /* ! 88: * XXX Compatibility ! 89: */ ! 90: if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); } ! 91: ! 92: if ((unsigned)uap->i >= fdp->fd_nfiles || ! 93: (fp = fdp->fd_ofiles[uap->i]) == NULL) ! 94: return (EBADF); ! 95: if (error = fdalloc(p, 0, &fd)) ! 96: return (error); ! 97: fdp->fd_ofiles[fd] = fp; ! 98: fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE; ! 99: fp->f_count++; ! 100: if (fd > fdp->fd_lastfile) ! 101: fdp->fd_lastfile = fd; ! 102: *retval = fd; ! 103: return (0); ! 104: } ! 105: ! 106: /* ! 107: * Duplicate a file descriptor to a particular value. ! 108: */ ! 109: /* ARGSUSED */ ! 110: dup2(p, uap, retval) ! 111: struct proc *p; ! 112: struct args { ! 113: u_int from; ! 114: u_int to; ! 115: } *uap; ! 116: int *retval; ! 117: { ! 118: register struct filedesc *fdp = p->p_fd; ! 119: register struct file *fp; ! 120: register u_int old = uap->from, new = uap->to; ! 121: int i, error; ! 122: ! 123: if (old >= fdp->fd_nfiles || ! 124: (fp = fdp->fd_ofiles[old]) == NULL || ! 125: new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur) ! 126: return (EBADF); ! 127: *retval = new; ! 128: if (old == new) ! 129: return (0); ! 130: if (new >= fdp->fd_nfiles) { ! 131: if (error = fdalloc(p, new, &i)) ! 132: return (error); ! 133: if (new != i) ! 134: panic("dup2: fdalloc"); ! 135: } else if (fdp->fd_ofiles[new]) { ! 136: if (fdp->fd_ofileflags[new] & UF_MAPPED) ! 137: (void) munmapfd(p, new); ! 138: /* ! 139: * dup2() must succeed even if the close has an error. ! 140: */ ! 141: (void) closef(fdp->fd_ofiles[new], p); ! 142: } ! 143: fdp->fd_ofiles[new] = fp; ! 144: fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE; ! 145: fp->f_count++; ! 146: if (new > fdp->fd_lastfile) ! 147: fdp->fd_lastfile = new; ! 148: return (0); ! 149: } ! 150: ! 151: /* ! 152: * The file control system call. ! 153: */ ! 154: /* ARGSUSED */ ! 155: fcntl(p, uap, retval) ! 156: struct proc *p; ! 157: register struct args { ! 158: int fd; ! 159: int cmd; ! 160: int arg; ! 161: } *uap; ! 162: int *retval; ! 163: { ! 164: register struct filedesc *fdp = p->p_fd; ! 165: register struct file *fp; ! 166: register char *pop; ! 167: struct vnode *vp; ! 168: int i, tmp, error, flg = F_POSIX; ! 169: struct flock fl; ! 170: ! 171: if ((unsigned)uap->fd >= fdp->fd_nfiles || ! 172: (fp = fdp->fd_ofiles[uap->fd]) == NULL) ! 173: return (EBADF); ! 174: pop = &fdp->fd_ofileflags[uap->fd]; ! 175: switch(uap->cmd) { ! 176: case F_DUPFD: ! 177: if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur) ! 178: return (EINVAL); ! 179: if (error = fdalloc(p, uap->arg, &i)) ! 180: return (error); ! 181: fdp->fd_ofiles[i] = fp; ! 182: fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE; ! 183: fp->f_count++; ! 184: if (i > fdp->fd_lastfile) ! 185: fdp->fd_lastfile = i; ! 186: *retval = i; ! 187: return (0); ! 188: ! 189: case F_GETFD: ! 190: *retval = *pop & 1; ! 191: return (0); ! 192: ! 193: case F_SETFD: ! 194: *pop = (*pop &~ 1) | (uap->arg & 1); ! 195: return (0); ! 196: ! 197: case F_GETFL: ! 198: *retval = OFLAGS(fp->f_flag); ! 199: return (0); ! 200: ! 201: case F_SETFL: ! 202: fp->f_flag &= ~FCNTLFLAGS; ! 203: fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS; ! 204: tmp = fp->f_flag & FNONBLOCK; ! 205: error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); ! 206: if (error) ! 207: return (error); ! 208: tmp = fp->f_flag & FASYNC; ! 209: error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); ! 210: if (!error) ! 211: return (0); ! 212: fp->f_flag &= ~FNONBLOCK; ! 213: tmp = 0; ! 214: (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); ! 215: return (error); ! 216: ! 217: case F_GETOWN: ! 218: if (fp->f_type == DTYPE_SOCKET) { ! 219: *retval = ((struct socket *)fp->f_data)->so_pgid; ! 220: return (0); ! 221: } ! 222: error = (*fp->f_ops->fo_ioctl) ! 223: (fp, (int)TIOCGPGRP, (caddr_t)retval, p); ! 224: *retval = -*retval; ! 225: return (error); ! 226: ! 227: case F_SETOWN: ! 228: if (fp->f_type == DTYPE_SOCKET) { ! 229: ((struct socket *)fp->f_data)->so_pgid = uap->arg; ! 230: return (0); ! 231: } ! 232: if (uap->arg <= 0) { ! 233: uap->arg = -uap->arg; ! 234: } else { ! 235: struct proc *p1 = pfind(uap->arg); ! 236: if (p1 == 0) ! 237: return (ESRCH); ! 238: uap->arg = p1->p_pgrp->pg_id; ! 239: } ! 240: return ((*fp->f_ops->fo_ioctl) ! 241: (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p)); ! 242: ! 243: case F_SETLKW: ! 244: flg |= F_WAIT; ! 245: /* Fall into F_SETLK */ ! 246: ! 247: case F_SETLK: ! 248: if (fp->f_type != DTYPE_VNODE) ! 249: return (EBADF); ! 250: vp = (struct vnode *)fp->f_data; ! 251: /* Copy in the lock structure */ ! 252: error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); ! 253: if (error) ! 254: return (error); ! 255: if (fl.l_whence == SEEK_CUR) ! 256: fl.l_start += fp->f_offset; ! 257: switch (fl.l_type) { ! 258: ! 259: case F_RDLCK: ! 260: if ((fp->f_flag & FREAD) == 0) ! 261: return (EBADF); ! 262: p->p_flag |= SADVLCK; ! 263: return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); ! 264: ! 265: case F_WRLCK: ! 266: if ((fp->f_flag & FWRITE) == 0) ! 267: return (EBADF); ! 268: p->p_flag |= SADVLCK; ! 269: return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg)); ! 270: ! 271: case F_UNLCK: ! 272: return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl, ! 273: F_POSIX)); ! 274: ! 275: default: ! 276: return (EINVAL); ! 277: } ! 278: ! 279: case F_GETLK: ! 280: if (fp->f_type != DTYPE_VNODE) ! 281: return (EBADF); ! 282: vp = (struct vnode *)fp->f_data; ! 283: /* Copy in the lock structure */ ! 284: error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl)); ! 285: if (error) ! 286: return (error); ! 287: if (fl.l_whence == SEEK_CUR) ! 288: fl.l_start += fp->f_offset; ! 289: if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX)) ! 290: return (error); ! 291: return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl))); ! 292: ! 293: default: ! 294: return (EINVAL); ! 295: } ! 296: /* NOTREACHED */ ! 297: } ! 298: ! 299: /* ! 300: * Close a file descriptor. ! 301: */ ! 302: /* ARGSUSED */ ! 303: close(p, uap, retval) ! 304: struct proc *p; ! 305: struct args { ! 306: int fd; ! 307: } *uap; ! 308: int *retval; ! 309: { ! 310: register struct filedesc *fdp = p->p_fd; ! 311: register struct file *fp; ! 312: register int fd = uap->fd; ! 313: register u_char *pf; ! 314: ! 315: if ((unsigned)fd >= fdp->fd_nfiles || ! 316: (fp = fdp->fd_ofiles[fd]) == NULL) ! 317: return (EBADF); ! 318: pf = (u_char *)&fdp->fd_ofileflags[fd]; ! 319: if (*pf & UF_MAPPED) ! 320: (void) munmapfd(p, fd); ! 321: fdp->fd_ofiles[fd] = NULL; ! 322: while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL) ! 323: fdp->fd_lastfile--; ! 324: if (fd < fdp->fd_freefile) ! 325: fdp->fd_freefile = fd; ! 326: *pf = 0; ! 327: return (closef(fp, p)); ! 328: } ! 329: ! 330: /* ! 331: * Return status information about a file descriptor. ! 332: */ ! 333: /* ARGSUSED */ ! 334: fstat(p, uap, retval) ! 335: struct proc *p; ! 336: register struct args { ! 337: int fd; ! 338: struct stat *sb; ! 339: } *uap; ! 340: int *retval; ! 341: { ! 342: register struct filedesc *fdp = p->p_fd; ! 343: register struct file *fp; ! 344: struct stat ub; ! 345: int error; ! 346: ! 347: if ((unsigned)uap->fd >= fdp->fd_nfiles || ! 348: (fp = fdp->fd_ofiles[uap->fd]) == NULL) ! 349: return (EBADF); ! 350: switch (fp->f_type) { ! 351: ! 352: case DTYPE_VNODE: ! 353: error = vn_stat((struct vnode *)fp->f_data, &ub, p); ! 354: break; ! 355: ! 356: case DTYPE_SOCKET: ! 357: error = soo_stat((struct socket *)fp->f_data, &ub); ! 358: break; ! 359: ! 360: default: ! 361: panic("fstat"); ! 362: /*NOTREACHED*/ ! 363: } ! 364: if (error == 0) ! 365: error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub)); ! 366: return (error); ! 367: } ! 368: ! 369: /* ! 370: * Allocate a file descriptor for the process. ! 371: */ ! 372: int fdexpand; ! 373: ! 374: fdalloc(p, want, result) ! 375: struct proc *p; ! 376: int want; ! 377: int *result; ! 378: { ! 379: register struct filedesc *fdp = p->p_fd; ! 380: register int i; ! 381: int lim, last, nfiles; ! 382: struct file **newofile; ! 383: char *newofileflags; ! 384: ! 385: /* ! 386: * Search for a free descriptor starting at the higher ! 387: * of want or fd_freefile. If that fails, consider ! 388: * expanding the ofile array. ! 389: */ ! 390: lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur; ! 391: for (;;) { ! 392: last = min(fdp->fd_nfiles, lim); ! 393: if ((i = want) < fdp->fd_freefile) ! 394: i = fdp->fd_freefile; ! 395: for (; i < last; i++) { ! 396: if (fdp->fd_ofiles[i] == NULL) { ! 397: fdp->fd_ofileflags[i] = 0; ! 398: if (i > fdp->fd_lastfile) ! 399: fdp->fd_lastfile = i; ! 400: if (want <= fdp->fd_freefile) ! 401: fdp->fd_freefile = i; ! 402: *result = i; ! 403: return (0); ! 404: } ! 405: } ! 406: ! 407: /* ! 408: * No space in current array. Expand? ! 409: */ ! 410: if (fdp->fd_nfiles >= lim) ! 411: return (EMFILE); ! 412: if (fdp->fd_nfiles < NDEXTENT) ! 413: nfiles = NDEXTENT; ! 414: else ! 415: nfiles = 2 * fdp->fd_nfiles; ! 416: MALLOC(newofile, struct file **, nfiles * OFILESIZE, ! 417: M_FILEDESC, M_WAITOK); ! 418: newofileflags = (char *) &newofile[nfiles]; ! 419: /* ! 420: * Copy the existing ofile and ofileflags arrays ! 421: * and zero the new portion of each array. ! 422: */ ! 423: bcopy(fdp->fd_ofiles, newofile, ! 424: (i = sizeof(struct file *) * fdp->fd_nfiles)); ! 425: bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i); ! 426: bcopy(fdp->fd_ofileflags, newofileflags, ! 427: (i = sizeof(char) * fdp->fd_nfiles)); ! 428: bzero(newofileflags + i, nfiles * sizeof(char) - i); ! 429: if (fdp->fd_nfiles > NDFILE) ! 430: FREE(fdp->fd_ofiles, M_FILEDESC); ! 431: fdp->fd_ofiles = newofile; ! 432: fdp->fd_ofileflags = newofileflags; ! 433: fdp->fd_nfiles = nfiles; ! 434: fdexpand++; ! 435: } ! 436: } ! 437: ! 438: /* ! 439: * Check to see whether n user file descriptors ! 440: * are available to the process p. ! 441: */ ! 442: fdavail(p, n) ! 443: struct proc *p; ! 444: register int n; ! 445: { ! 446: register struct filedesc *fdp = p->p_fd; ! 447: register struct file **fpp; ! 448: register int i; ! 449: ! 450: if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 && ! 451: (n -= i) <= 0) ! 452: return (1); ! 453: fpp = &fdp->fd_ofiles[fdp->fd_freefile]; ! 454: for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++) ! 455: if (*fpp == NULL && --n <= 0) ! 456: return (1); ! 457: return (0); ! 458: } ! 459: ! 460: /* ! 461: * Create a new open file structure and allocate ! 462: * a file decriptor for the process that refers to it. ! 463: */ ! 464: falloc(p, resultfp, resultfd) ! 465: register struct proc *p; ! 466: struct file **resultfp; ! 467: int *resultfd; ! 468: { ! 469: register struct file *fp, *fq, **fpp; ! 470: int error, i; ! 471: ! 472: if (error = fdalloc(p, 0, &i)) ! 473: return (error); ! 474: if (nfiles >= maxfiles) { ! 475: tablefull("file"); ! 476: return (ENFILE); ! 477: } ! 478: /* ! 479: * Allocate a new file descriptor. ! 480: * If the process has file descriptor zero open, add to the list ! 481: * of open files at that point, otherwise put it at the front of ! 482: * the list of open files. ! 483: */ ! 484: nfiles++; ! 485: MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK); ! 486: if (fq = p->p_fd->fd_ofiles[0]) ! 487: fpp = &fq->f_filef; ! 488: else ! 489: fpp = &filehead; ! 490: p->p_fd->fd_ofiles[i] = fp; ! 491: if (fq = *fpp) ! 492: fq->f_fileb = &fp->f_filef; ! 493: fp->f_filef = fq; ! 494: fp->f_fileb = fpp; ! 495: *fpp = fp; ! 496: fp->f_count = 1; ! 497: fp->f_msgcount = 0; ! 498: fp->f_offset = 0; ! 499: fp->f_cred = p->p_ucred; ! 500: crhold(fp->f_cred); ! 501: if (resultfp) ! 502: *resultfp = fp; ! 503: if (resultfd) ! 504: *resultfd = i; ! 505: return (0); ! 506: } ! 507: ! 508: /* ! 509: * Free a file descriptor. ! 510: */ ! 511: ffree(fp) ! 512: register struct file *fp; ! 513: { ! 514: register struct file *fq; ! 515: ! 516: if (fq = fp->f_filef) ! 517: fq->f_fileb = fp->f_fileb; ! 518: *fp->f_fileb = fq; ! 519: crfree(fp->f_cred); ! 520: #ifdef DIAGNOSTIC ! 521: fp->f_filef = NULL; ! 522: fp->f_fileb = NULL; ! 523: fp->f_count = 0; ! 524: #endif ! 525: nfiles--; ! 526: FREE(fp, M_FILE); ! 527: } ! 528: ! 529: /* ! 530: * Copy a filedesc structure. ! 531: */ ! 532: struct filedesc * ! 533: fdcopy(p) ! 534: struct proc *p; ! 535: { ! 536: register struct filedesc *newfdp, *fdp = p->p_fd; ! 537: register struct file **fpp; ! 538: register int i; ! 539: ! 540: MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0), ! 541: M_FILEDESC, M_WAITOK); ! 542: bcopy(fdp, newfdp, sizeof(struct filedesc)); ! 543: VREF(newfdp->fd_cdir); ! 544: if (newfdp->fd_rdir) ! 545: VREF(newfdp->fd_rdir); ! 546: newfdp->fd_refcnt = 1; ! 547: ! 548: /* ! 549: * If the number of open files fits in the internal arrays ! 550: * of the open file structure, use them, otherwise allocate ! 551: * additional memory for the number of descriptors currently ! 552: * in use. ! 553: */ ! 554: if (newfdp->fd_lastfile < NDFILE) { ! 555: newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles; ! 556: newfdp->fd_ofileflags = ! 557: ((struct filedesc0 *) newfdp)->fd_dfileflags; ! 558: i = NDFILE; ! 559: } else { ! 560: /* ! 561: * Compute the smallest multiple of NDEXTENT needed ! 562: * for the file descriptors currently in use, ! 563: * allowing the table to shrink. ! 564: */ ! 565: i = newfdp->fd_nfiles; ! 566: while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2) ! 567: i /= 2; ! 568: MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE, ! 569: M_FILEDESC, M_WAITOK); ! 570: newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i]; ! 571: } ! 572: newfdp->fd_nfiles = i; ! 573: bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **)); ! 574: bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char)); ! 575: fpp = newfdp->fd_ofiles; ! 576: for (i = newfdp->fd_lastfile; i-- >= 0; fpp++) ! 577: if (*fpp != NULL) ! 578: (*fpp)->f_count++; ! 579: return (newfdp); ! 580: } ! 581: ! 582: /* ! 583: * Release a filedesc structure. ! 584: */ ! 585: void ! 586: fdfree(p) ! 587: struct proc *p; ! 588: { ! 589: register struct filedesc *fdp = p->p_fd; ! 590: struct file **fpp; ! 591: register int i; ! 592: ! 593: if (--fdp->fd_refcnt > 0) ! 594: return; ! 595: fpp = fdp->fd_ofiles; ! 596: for (i = fdp->fd_lastfile; i-- >= 0; fpp++) ! 597: if (*fpp) ! 598: (void) closef(*fpp, p); ! 599: if (fdp->fd_nfiles > NDFILE) ! 600: FREE(fdp->fd_ofiles, M_FILEDESC); ! 601: vrele(fdp->fd_cdir); ! 602: if (fdp->fd_rdir) ! 603: vrele(fdp->fd_rdir); ! 604: FREE(fdp, M_FILEDESC); ! 605: } ! 606: ! 607: /* ! 608: * Internal form of close. ! 609: * Decrement reference count on file structure. ! 610: */ ! 611: closef(fp, p) ! 612: register struct file *fp; ! 613: register struct proc *p; ! 614: { ! 615: struct vnode *vp; ! 616: struct flock lf; ! 617: int error; ! 618: ! 619: if (fp == NULL) ! 620: return (0); ! 621: /* ! 622: * POSIX record locking dictates that any close releases ALL ! 623: * locks owned by this process. This is handled by setting ! 624: * a flag in the unlock to free ONLY locks obeying POSIX ! 625: * semantics, and not to free BSD-style file locks. ! 626: */ ! 627: if ((p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) { ! 628: lf.l_whence = SEEK_SET; ! 629: lf.l_start = 0; ! 630: lf.l_len = 0; ! 631: lf.l_type = F_UNLCK; ! 632: vp = (struct vnode *)fp->f_data; ! 633: (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX); ! 634: } ! 635: if (--fp->f_count > 0) ! 636: return (0); ! 637: if (fp->f_count < 0) ! 638: panic("closef: count < 0"); ! 639: if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) { ! 640: lf.l_whence = SEEK_SET; ! 641: lf.l_start = 0; ! 642: lf.l_len = 0; ! 643: lf.l_type = F_UNLCK; ! 644: vp = (struct vnode *)fp->f_data; ! 645: (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK); ! 646: } ! 647: error = (*fp->f_ops->fo_close)(fp, p); ! 648: ffree(fp); ! 649: return (error); ! 650: } ! 651: ! 652: /* ! 653: * Apply an advisory lock on a file descriptor. ! 654: * ! 655: * Just attempt to get a record lock of the requested type on ! 656: * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0). ! 657: */ ! 658: ! 659: /* ARGSUSED */ ! 660: flock(p, uap, retval) ! 661: struct proc *p; ! 662: register struct args { ! 663: int fd; ! 664: int how; ! 665: } *uap; ! 666: int *retval; ! 667: { ! 668: register struct filedesc *fdp = p->p_fd; ! 669: register struct file *fp; ! 670: struct vnode *vp; ! 671: struct flock lf; ! 672: int error; ! 673: ! 674: if ((unsigned)uap->fd >= fdp->fd_nfiles || ! 675: (fp = fdp->fd_ofiles[uap->fd]) == NULL) ! 676: return (EBADF); ! 677: if (fp->f_type != DTYPE_VNODE) ! 678: return (EOPNOTSUPP); ! 679: vp = (struct vnode *)fp->f_data; ! 680: lf.l_whence = SEEK_SET; ! 681: lf.l_start = 0; ! 682: lf.l_len = 0; ! 683: if (uap->how & LOCK_UN) { ! 684: lf.l_type = F_UNLCK; ! 685: fp->f_flag &= ~FHASLOCK; ! 686: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK)); ! 687: } ! 688: if (uap->how & LOCK_EX) ! 689: lf.l_type = F_WRLCK; ! 690: else if (uap->how & LOCK_SH) ! 691: lf.l_type = F_RDLCK; ! 692: else ! 693: return (EBADF); ! 694: fp->f_flag |= FHASLOCK; ! 695: if (uap->how & LOCK_NB) ! 696: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK)); ! 697: return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT)); ! 698: } ! 699: ! 700: /* ! 701: * File Descriptor pseudo-device driver (/dev/fd/). ! 702: * ! 703: * Opening minor device N dup()s the file (if any) connected to file ! 704: * descriptor N belonging to the calling process. Note that this driver ! 705: * consists of only the ``open()'' routine, because all subsequent ! 706: * references to this file will be direct to the other driver. ! 707: */ ! 708: /* ARGSUSED */ ! 709: fdopen(dev, mode, type) ! 710: dev_t dev; ! 711: int mode, type; ! 712: { ! 713: ! 714: /* ! 715: * XXX Kludge: set curproc->p_dupfd to contain the value of the ! 716: * the file descriptor being sought for duplication. The error ! 717: * return ensures that the vnode for this device will be released ! 718: * by vn_open. Open will detect this special error and take the ! 719: * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN ! 720: * will simply report the error. ! 721: */ ! 722: curproc->p_dupfd = minor(dev); /* XXX */ ! 723: return (ENODEV); ! 724: } ! 725: ! 726: /* ! 727: * Duplicate the specified descriptor to a free descriptor. ! 728: */ ! 729: dupfdopen(fdp, indx, dfd, mode) ! 730: register struct filedesc *fdp; ! 731: register int indx, dfd; ! 732: int mode; ! 733: { ! 734: register struct file *wfp; ! 735: struct file *fp; ! 736: ! 737: /* ! 738: * If the to-be-dup'd fd number is greater than the allowed number ! 739: * of file descriptors, or the fd to be dup'd has already been ! 740: * closed, reject. Note, check for new == old is necessary as ! 741: * falloc could allocate an already closed to-be-dup'd descriptor ! 742: * as the new descriptor. ! 743: */ ! 744: fp = fdp->fd_ofiles[indx]; ! 745: if ((u_int)dfd >= fdp->fd_nfiles || ! 746: (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp) ! 747: return (EBADF); ! 748: ! 749: /* ! 750: * Check that the mode the file is being opened for is a subset ! 751: * of the mode of the existing descriptor. ! 752: */ ! 753: if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) ! 754: return (EACCES); ! 755: fdp->fd_ofiles[indx] = wfp; ! 756: fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd]; ! 757: wfp->f_count++; ! 758: if (indx > fdp->fd_lastfile) ! 759: fdp->fd_lastfile = indx; ! 760: return (0); ! 761: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.