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