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