xref: /csrg-svn/sys/kern/kern_descrip.c (revision 45914)
1 /*
2  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_descrip.c	7.17 (Berkeley) 01/10/91
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "user.h"
13 #include "filedesc.h"
14 #include "kernel.h"
15 #include "vnode.h"
16 #include "proc.h"
17 #include "file.h"
18 #include "socket.h"
19 #include "socketvar.h"
20 #include "stat.h"
21 #include "ioctl.h"
22 #include "malloc.h"
23 #include "syslog.h"
24 
25 /*
26  * Descriptor management.
27  */
28 int nofile = NOFILE;		/* per-process maximum open files */
29 
30 /*
31  * System calls on descriptors.
32  */
33 /* ARGSUSED */
34 getdtablesize(p, uap, retval)
35 	struct proc *p;
36 	struct args *uap;
37 	int *retval;
38 {
39 
40 	*retval = nofile;
41 	return (0);
42 }
43 
44 /*
45  * Duplicate a file descriptor.
46  */
47 /* ARGSUSED */
48 dup(p, uap, retval)
49 	struct proc *p;
50 	struct args {
51 		int	i;
52 	} *uap;
53 	int *retval;
54 {
55 	register struct filedesc *fdp = p->p_fd;
56 	struct file *fp;
57 	int fd, error;
58 
59 	/*
60 	 * XXX Compatibility
61 	 */
62 	if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); }
63 
64 	if ((unsigned)uap->i >= fdp->fd_maxfiles ||
65 	    (fp = OFILE(fdp, uap->i)) == NULL)
66 		return (EBADF);
67 	if (error = ufalloc(fdp, 0, &fd))
68 		return (error);
69 	OFILE(fdp, fd) = fp;
70 	OFILEFLAGS(fdp, fd) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE;
71 	fp->f_count++;
72 	if (fd > fdp->fd_lastfile)
73 		fdp->fd_lastfile = fd;
74 	*retval = fd;
75 	return (0);
76 }
77 
78 /*
79  * Duplicate a file descriptor to a particular value.
80  */
81 /* ARGSUSED */
82 dup2(p, uap, retval)
83 	struct proc *p;
84 	register struct args {
85 		int	i;
86 		int	j;
87 	} *uap;
88 	int *retval;
89 {
90 	register struct filedesc *fdp = p->p_fd;
91 	register struct file *fp;
92 	int i, error;
93 
94 	if ((unsigned)uap->i >= fdp->fd_maxfiles ||
95 	    (fp = OFILE(fdp, uap->i)) == NULL ||
96 	    (unsigned)uap->j >= nofile)
97 		return (EBADF);
98 	*retval = uap->j;
99 	if (uap->i == uap->j)
100 		return (0);
101 	if ((unsigned)uap->j >= fdp->fd_maxfiles) {
102 		if (error = ufalloc(fdp, uap->j, &i))
103 			return (error);
104 		if (uap->j != i)
105 			panic("dup2: ufalloc");
106 	} else if (OFILE(fdp, uap->j)) {
107 		if (OFILEFLAGS(fdp, uap->j) & UF_MAPPED)
108 			(void) munmapfd(p, uap->j);
109 		error = closef(OFILE(fdp, uap->j));
110 	}
111 	OFILE(fdp, uap->j) = fp;
112 	OFILEFLAGS(fdp, uap->j) = OFILEFLAGS(fdp, uap->i) &~ UF_EXCLOSE;
113 	fp->f_count++;
114 	if (uap->j > fdp->fd_lastfile)
115 		fdp->fd_lastfile = uap->j;
116 	/*
117 	 * dup2() must succeed even though the close had an error.
118 	 */
119 	error = 0;		/* XXX */
120 	return (error);
121 }
122 
123 /*
124  * The file control system call.
125  */
126 /* ARGSUSED */
127 fcntl(p, uap, retval)
128 	struct proc *p;
129 	register struct args {
130 		int	fdes;
131 		int	cmd;
132 		int	arg;
133 	} *uap;
134 	int *retval;
135 {
136 	register struct filedesc *fdp = p->p_fd;
137 	register struct file *fp;
138 	register char *pop;
139 	int i, error;
140 
141 	if ((unsigned)uap->fdes >= fdp->fd_maxfiles ||
142 	    (fp = OFILE(fdp, uap->fdes)) == NULL)
143 		return (EBADF);
144 	pop = &OFILEFLAGS(fdp, uap->fdes);
145 	switch(uap->cmd) {
146 	case F_DUPFD:
147 		if ((unsigned)uap->arg >= nofile)
148 			return (EINVAL);
149 		if (error = ufalloc(fdp, uap->arg, &i))
150 			return (error);
151 		OFILE(fdp, i) = fp;
152 		OFILEFLAGS(fdp, i) = *pop &~ UF_EXCLOSE;
153 		fp->f_count++;
154 		if (i > fdp->fd_lastfile)
155 			fdp->fd_lastfile = i;
156 		*retval = i;
157 		return (0);
158 
159 	case F_GETFD:
160 		*retval = *pop & 1;
161 		return (0);
162 
163 	case F_SETFD:
164 		*pop = (*pop &~ 1) | (uap->arg & 1);
165 		return (0);
166 
167 	case F_GETFL:
168 		*retval = fp->f_flag + FOPEN;
169 		return (0);
170 
171 	case F_SETFL:
172 		fp->f_flag &= FCNTLCANT;
173 		fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
174 		if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY))
175 			return (error);
176 		if (error = fset(fp, FASYNC, fp->f_flag & FASYNC))
177 			(void) fset(fp, FNDELAY, 0);
178 		return (error);
179 
180 	case F_GETOWN:
181 		return (fgetown(fp, retval));
182 
183 	case F_SETOWN:
184 		return (fsetown(fp, uap->arg));
185 
186 	default:
187 		return (EINVAL);
188 	}
189 	/* NOTREACHED */
190 }
191 
192 fset(fp, bit, value)
193 	struct file *fp;
194 	int bit, value;
195 {
196 
197 	if (value)
198 		fp->f_flag |= bit;
199 	else
200 		fp->f_flag &= ~bit;
201 	return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
202 	    (caddr_t)&value));
203 }
204 
205 fgetown(fp, valuep)
206 	struct file *fp;
207 	int *valuep;
208 {
209 	int error;
210 
211 	switch (fp->f_type) {
212 
213 	case DTYPE_SOCKET:
214 		*valuep = ((struct socket *)fp->f_data)->so_pgid;
215 		return (0);
216 
217 	default:
218 		error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
219 		*valuep = -*valuep;
220 		return (error);
221 	}
222 }
223 
224 fsetown(fp, value)
225 	struct file *fp;
226 	int value;
227 {
228 
229 	if (fp->f_type == DTYPE_SOCKET) {
230 		((struct socket *)fp->f_data)->so_pgid = value;
231 		return (0);
232 	}
233 	if (value > 0) {
234 		struct proc *p = pfind(value);
235 		if (p == 0)
236 			return (ESRCH);
237 		value = p->p_pgrp->pg_id;
238 	} else
239 		value = -value;
240 	return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
241 }
242 
243 fioctl(fp, cmd, value)
244 	struct file *fp;
245 	int cmd;
246 	caddr_t value;
247 {
248 
249 	return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
250 }
251 
252 /*
253  * Close a file descriptor.
254  */
255 /* ARGSUSED */
256 close(p, uap, retval)
257 	struct proc *p;
258 	struct args {
259 		int	fdes;
260 	} *uap;
261 	int *retval;
262 {
263 	register struct filedesc *fdp = p->p_fd;
264 	register struct file *fp;
265 	register u_char *pf;
266 
267 	if ((unsigned)uap->fdes >= fdp->fd_maxfiles ||
268 	    (fp = OFILE(fdp, uap->fdes)) == NULL)
269 		return (EBADF);
270 	pf = (u_char *)&OFILEFLAGS(fdp, uap->fdes);
271 	if (*pf & UF_MAPPED)
272 		(void) munmapfd(p, uap->fdes);
273 	OFILE(fdp, uap->fdes) = NULL;
274 	while (fdp->fd_lastfile >= 0 && OFILE(fdp, fdp->fd_lastfile) == NULL)
275 		fdp->fd_lastfile--;
276 	*pf = 0;
277 	return (closef(fp));
278 }
279 
280 /*
281  * Return status information about a file descriptor.
282  */
283 /* ARGSUSED */
284 fstat(p, uap, retval)
285 	struct proc *p;
286 	register struct args {
287 		int	fdes;
288 		struct	stat *sb;
289 	} *uap;
290 	int *retval;
291 {
292 	register struct filedesc *fdp = p->p_fd;
293 	register struct file *fp;
294 	struct stat ub;
295 	int error;
296 
297 	if ((unsigned)uap->fdes >= fdp->fd_maxfiles ||
298 	    (fp = OFILE(fdp, uap->fdes)) == NULL)
299 		return (EBADF);
300 	switch (fp->f_type) {
301 
302 	case DTYPE_VNODE:
303 		error = vn_stat((struct vnode *)fp->f_data, &ub);
304 		break;
305 
306 	case DTYPE_SOCKET:
307 		error = soo_stat((struct socket *)fp->f_data, &ub);
308 		break;
309 
310 	default:
311 		panic("fstat");
312 		/*NOTREACHED*/
313 	}
314 	if (error == 0)
315 		error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
316 	return (error);
317 }
318 
319 /*
320  * Allocate a user file descriptor.
321  */
322 int fdexpand, fdreexpand;
323 
324 ufalloc(fdp, want, result)
325 	register struct filedesc *fdp;
326 	register int want;
327 	int *result;
328 {
329 	int last, osize, ofiles, nfiles;
330 	struct file **newofile;
331 	char *newofileflags;
332 
333 	for (;;) {
334 		last = (fdp->fd_maxfiles < nofile) ? fdp->fd_maxfiles : nofile;
335 		for (; want < last; want++) {
336 			if (OFILE(fdp, want) == NULL) {
337 				OFILEFLAGS(fdp, want) = 0;
338 				if (want > fdp->fd_lastfile)
339 					fdp->fd_lastfile = want;
340 				*result = want;
341 				return (0);
342 			}
343 		}
344 		if (fdp->fd_maxfiles >= nofile)
345 			return (EMFILE);
346 		if (fdp->fd_maxfiles == NDFILE) {
347 			fdp->fd_moreofiles = (struct file **)
348 			    malloc(NDEXTENT * OFILESIZE, M_FILE, M_WAITOK);
349 			fdp->fd_moreofileflags =
350 			    (char *)&fdp->fd_moreofiles[NDEXTENT];
351 			bzero((char *)fdp->fd_moreofiles, NDEXTENT * OFILESIZE);
352 			fdp->fd_maxfiles = NDFILE + NDEXTENT;
353 			fdexpand++;
354 			continue;
355 		}
356 		ofiles = fdp->fd_maxfiles - NDFILE;
357 		osize = ofiles * OFILESIZE;
358 		nfiles = (2 * osize) / OFILESIZE;
359 		newofile = (struct file **) malloc(2 * osize, M_FILE, M_WAITOK);
360 		newofileflags = (char *)&newofile[nfiles];
361 		bzero((char *)newofile, 2 * osize);
362 		bcopy((char *)fdp->fd_moreofiles, (char *)newofile,
363 			sizeof(struct file *) * ofiles);
364 		bcopy((char *)fdp->fd_moreofileflags, (char *)newofileflags,
365 			sizeof(char) * ofiles);
366 		free(fdp->fd_moreofiles, M_FILE);
367 		fdp->fd_moreofiles = newofile;
368 		fdp->fd_moreofileflags = newofileflags;
369 		fdp->fd_maxfiles = NDFILE + nfiles;
370 		fdreexpand++;
371 	}
372 }
373 
374 /*
375  * Check to see if any user file descriptors are available.
376  */
377 ufavail(fdp)
378 	register struct filedesc *fdp;
379 {
380 	register int i, avail;
381 
382 	avail = nofile - fdp->fd_maxfiles;
383 	for (i = 0; i < fdp->fd_maxfiles; i++)
384 		if (OFILE(fdp, i) == NULL)
385 			avail++;
386 	return (avail);
387 }
388 
389 struct	file *lastf;
390 /*
391  * Allocate a user file descriptor
392  * and a file structure.
393  * Initialize the descriptor
394  * to point at the file structure.
395  */
396 falloc(p, resultfp, resultfd)
397 	register struct proc *p;
398 	struct file **resultfp;
399 	int *resultfd;
400 {
401 	register struct file *fp;
402 	int error, i;
403 
404 	if (error = ufalloc(p->p_fd, 0, &i))
405 		return (error);
406 	if (lastf == 0)
407 		lastf = file;
408 	for (fp = lastf; fp < fileNFILE; fp++)
409 		if (fp->f_count == 0)
410 			goto slot;
411 	for (fp = file; fp < lastf; fp++)
412 		if (fp->f_count == 0)
413 			goto slot;
414 	tablefull("file");
415 	return (ENFILE);
416 slot:
417 	OFILE(p->p_fd, i) = fp;
418 	fp->f_count = 1;
419 	fp->f_data = 0;
420 	fp->f_offset = 0;
421 	fp->f_cred = u.u_cred;
422 	crhold(fp->f_cred);
423 	lastf = fp + 1;
424 	if (resultfp)
425 		*resultfp = fp;
426 	if (resultfd)
427 		*resultfd = i;
428 	return (0);
429 }
430 
431 /*
432  * Duplicate a filedesc structure.
433  */
434 struct filedesc *
435 fddup(fdp, justref)
436 	register struct filedesc *fdp;
437 	int justref;
438 {
439 	register struct filedesc *newfdp;
440 	register struct file *fp;
441 	register int i;
442 	int j, last;
443 
444 	if (justref) {
445 		fdp->fd_refcnt++;
446 		return (fdp);
447 	}
448 	MALLOC(newfdp, struct filedesc *, sizeof(*fdp), M_FILE, M_WAITOK);
449 	bcopy((char *)fdp, (char *)newfdp, sizeof(*fdp));
450 	VREF(newfdp->fd_cdir);
451 	if (newfdp->fd_rdir)
452 		VREF(newfdp->fd_rdir);
453 	newfdp->fd_refcnt = 1;
454 	newfdp->fd_maxfiles = NDFILE;
455 	if (fdp->fd_lastfile > NDFILE &&
456 	    ufalloc(newfdp, fdp->fd_lastfile, &j)) {
457 		log(LOG_ERR, "fddup: lost file descriptor(s)");
458 		last = newfdp->fd_maxfiles;
459 	} else
460 		last = fdp->fd_lastfile;
461 	for (i = 0; i <= last; i++) {
462 		fp = OFILE(fdp, i);
463 		if (fp == NULL)
464 			continue;
465 		fp->f_count++;
466 		OFILE(newfdp, i) = fp;
467 		OFILEFLAGS(newfdp, i) = OFILEFLAGS(fdp, i);
468 	}
469 	return (newfdp);
470 }
471 
472 /*
473  * Release a filedesc structure.
474  */
475 fdrele(fdp)
476 	register struct filedesc *fdp;
477 {
478 	struct file *f;
479 	register int i;
480 
481 	if (fdp->fd_refcnt > 1) {
482 		fdp->fd_refcnt--;
483 		return;
484 	}
485 	for (i = 0; i <= fdp->fd_lastfile; i++) {
486 		if (f = OFILE(fdp, i)) {
487 			OFILE(fdp, i) = NULL;
488 			OFILEFLAGS(fdp, i) = 0;
489 			(void) closef(f);
490 		}
491 	}
492 	if (fdp->fd_maxfiles > NDFILE)
493 		FREE(fdp->fd_moreofiles, M_FILE);
494 	vrele(fdp->fd_cdir);
495 	if (fdp->fd_rdir)
496 		vrele(fdp->fd_rdir);
497 	FREE(fdp, M_FILE);
498 }
499 
500 /*
501  * Internal form of close.
502  * Decrement reference count on file structure.
503  */
504 closef(fp)
505 	register struct file *fp;
506 {
507 	int error;
508 
509 	if (fp == NULL)
510 		return (0);
511 	if (fp->f_count > 1) {
512 		fp->f_count--;
513 		return (0);
514 	}
515 	if (fp->f_count < 1)
516 		panic("closef: count < 1");
517 	error = (*fp->f_ops->fo_close)(fp);
518 	crfree(fp->f_cred);
519 	fp->f_count = 0;
520 	return (error);
521 }
522 
523 /*
524  * Apply an advisory lock on a file descriptor.
525  */
526 /* ARGSUSED */
527 flock(p, uap, retval)
528 	struct proc *p;
529 	register struct args {
530 		int	fdes;
531 		int	how;
532 	} *uap;
533 	int *retval;
534 {
535 	register struct filedesc *fdp = p->p_fd;
536 	register struct file *fp;
537 
538 	if ((unsigned)uap->fdes >= fdp->fd_maxfiles ||
539 	    (fp = OFILE(fdp, uap->fdes)) == NULL)
540 		return (EBADF);
541 	if (fp->f_type != DTYPE_VNODE)
542 		return (EOPNOTSUPP);
543 	if (uap->how & LOCK_UN) {
544 		vn_unlock(fp, FSHLOCK|FEXLOCK);
545 		return (0);
546 	}
547 	if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
548 		return (0);				/* error? */
549 	if (uap->how & LOCK_EX)
550 		uap->how &= ~LOCK_SH;
551 	/* avoid work... */
552 	if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
553 	    (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
554 		return (0);
555 	return (vn_lock(fp, uap->how));
556 }
557 
558 /*
559  * File Descriptor pseudo-device driver (/dev/fd/).
560  *
561  * Opening minor device N dup()s the file (if any) connected to file
562  * descriptor N belonging to the calling process.  Note that this driver
563  * consists of only the ``open()'' routine, because all subsequent
564  * references to this file will be direct to the other driver.
565  */
566 /* ARGSUSED */
567 fdopen(dev, mode, type)
568 	dev_t dev;
569 	int mode, type;
570 {
571 	struct proc *p = u.u_procp;		/* XXX */
572 
573 	/*
574 	 * XXX Kludge: set p->p_dupfd to contain the value of the
575 	 * the file descriptor being sought for duplication. The error
576 	 * return ensures that the vnode for this device will be released
577 	 * by vn_open. Open will detect this special error and take the
578 	 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
579 	 * will simply report the error.
580 	 */
581 	p->p_dupfd = minor(dev);
582 	return (ENODEV);
583 }
584 
585 /*
586  * Duplicate the specified descriptor to a free descriptor.
587  */
588 dupfdopen(fdp, indx, dfd, mode)
589 	register struct filedesc *fdp;
590 	register int indx, dfd;
591 	int mode;
592 {
593 	register struct file *wfp;
594 	struct file *fp;
595 
596 	/*
597 	 * If the to-be-dup'd fd number is greater than the allowed number
598 	 * of file descriptors, or the fd to be dup'd has already been
599 	 * closed, reject.  Note, check for new == old is necessary as
600 	 * falloc could allocate an already closed to-be-dup'd descriptor
601 	 * as the new descriptor.
602 	 */
603 	fp = OFILE(fdp, indx);
604 	if ((u_int)dfd >= fdp->fd_maxfiles || (wfp = OFILE(fdp, dfd)) == NULL ||
605 	    fp == wfp)
606 		return (EBADF);
607 
608 	/*
609 	 * Check that the mode the file is being opened for is a subset
610 	 * of the mode of the existing descriptor.
611 	 */
612 	if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
613 		return (EACCES);
614 	OFILE(fdp, indx) = wfp;
615 	OFILEFLAGS(fdp, indx) = OFILEFLAGS(fdp, dfd);
616 	wfp->f_count++;
617 	if (indx > fdp->fd_lastfile)
618 		fdp->fd_lastfile = indx;
619 	return (0);
620 }
621 
622 #if defined(vax) || defined(tahoe)
623 /*
624  * Brain dead routines to compensate for limitations in PCC
625  */
626 struct file **
627 ofilefunc(fdp, indx)
628 	struct filedesc *fdp;
629 	int indx;
630 {
631 
632 	if (indx < NDFILE)
633 		return (&fdp->fd_ofile[indx]);
634 	return (&fdp->fd_moreofiles[indx - NDFILE]);
635 }
636 
637 char *
638 ofileflagsfunc(fdp, indx)
639 	struct filedesc *fdp;
640 	int indx;
641 {
642 
643 	if (indx < NDFILE)
644 		return (&fdp->fd_ofileflags[indx]);
645 	return (&fdp->fd_moreofileflags[indx - NDFILE]);
646 }
647 #endif
648