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