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