|
|
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.