kern_descrip.c revision 1.52 1 /* $NetBSD: kern_descrip.c,v 1.52 1998/07/31 22:50:49 perry Exp $ */
2
3 /*
4 * Copyright (c) 1982, 1986, 1989, 1991, 1993
5 * The Regents of the University of California. All rights reserved.
6 * (c) UNIX System Laboratories, Inc.
7 * All or some portions of this file are derived from material licensed
8 * to the University of California by American Telephone and Telegraph
9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
10 * the permission of UNIX System Laboratories, Inc.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the University of
23 * California, Berkeley and its contributors.
24 * 4. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 * SUCH DAMAGE.
39 *
40 * @(#)kern_descrip.c 8.8 (Berkeley) 2/14/95
41 */
42
43 #include "opt_uvm.h"
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/filedesc.h>
48 #include <sys/kernel.h>
49 #include <sys/vnode.h>
50 #include <sys/proc.h>
51 #include <sys/file.h>
52 #include <sys/socket.h>
53 #include <sys/socketvar.h>
54 #include <sys/stat.h>
55 #include <sys/ioctl.h>
56 #include <sys/fcntl.h>
57 #include <sys/malloc.h>
58 #include <sys/syslog.h>
59 #include <sys/unistd.h>
60 #include <sys/resourcevar.h>
61 #include <sys/conf.h>
62
63 #include <sys/mount.h>
64 #include <sys/syscallargs.h>
65
66 #include <vm/vm.h>
67
68 /*
69 * Descriptor management.
70 */
71 struct filelist filehead; /* head of list of open files */
72 int nfiles; /* actual number of open files */
73
74 static __inline void fd_used __P((struct filedesc *, int));
75 static __inline void fd_unused __P((struct filedesc *, int));
76 int finishdup __P((struct filedesc *, int, int, register_t *));
77
78 static __inline void
79 fd_used(fdp, fd)
80 register struct filedesc *fdp;
81 register int fd;
82 {
83
84 if (fd > fdp->fd_lastfile)
85 fdp->fd_lastfile = fd;
86 }
87
88 static __inline void
89 fd_unused(fdp, fd)
90 register struct filedesc *fdp;
91 register int fd;
92 {
93
94 if (fd < fdp->fd_freefile)
95 fdp->fd_freefile = fd;
96 #ifdef DIAGNOSTIC
97 if (fd > fdp->fd_lastfile)
98 panic("fd_unused: fd_lastfile inconsistent");
99 #endif
100 if (fd == fdp->fd_lastfile) {
101 do {
102 fd--;
103 } while (fd >= 0 && fdp->fd_ofiles[fd] == NULL);
104 fdp->fd_lastfile = fd;
105 }
106 }
107
108 /*
109 * System calls on descriptors.
110 */
111
112 /*
113 * Duplicate a file descriptor.
114 */
115 /* ARGSUSED */
116 int
117 sys_dup(p, v, retval)
118 struct proc *p;
119 void *v;
120 register_t *retval;
121 {
122 struct sys_dup_args /* {
123 syscallarg(int) fd;
124 } */ *uap = v;
125 register struct filedesc *fdp = p->p_fd;
126 register int old = SCARG(uap, fd);
127 int new;
128 int error;
129
130 if ((u_int)old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL)
131 return (EBADF);
132 if ((error = fdalloc(p, 0, &new)) != 0)
133 return (error);
134 return (finishdup(fdp, old, new, retval));
135 }
136
137 /*
138 * Duplicate a file descriptor to a particular value.
139 */
140 /* ARGSUSED */
141 int
142 sys_dup2(p, v, retval)
143 struct proc *p;
144 void *v;
145 register_t *retval;
146 {
147 struct sys_dup2_args /* {
148 syscallarg(int) from;
149 syscallarg(int) to;
150 } */ *uap = v;
151 register struct filedesc *fdp = p->p_fd;
152 register int old = SCARG(uap, from), new = SCARG(uap, to);
153 int i, error;
154
155 if ((u_int)old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL ||
156 (u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
157 (u_int)new >= maxfiles)
158 return (EBADF);
159 if (old == new) {
160 *retval = new;
161 return (0);
162 }
163 if (new >= fdp->fd_nfiles) {
164 if ((error = fdalloc(p, new, &i)) != 0)
165 return (error);
166 if (new != i)
167 panic("dup2: fdalloc");
168 } else {
169 (void) fdrelease(p, new);
170 }
171 return (finishdup(fdp, old, new, retval));
172 }
173
174 /*
175 * The file control system call.
176 */
177 /* ARGSUSED */
178 int
179 sys_fcntl(p, v, retval)
180 struct proc *p;
181 void *v;
182 register_t *retval;
183 {
184 register struct sys_fcntl_args /* {
185 syscallarg(int) fd;
186 syscallarg(int) cmd;
187 syscallarg(void *) arg;
188 } */ *uap = v;
189 int fd = SCARG(uap, fd);
190 register struct filedesc *fdp = p->p_fd;
191 register struct file *fp;
192 struct vnode *vp;
193 int i, tmp, error, flg = F_POSIX;
194 struct flock fl;
195 int newmin;
196
197 if ((u_int)fd >= fdp->fd_nfiles ||
198 (fp = fdp->fd_ofiles[fd]) == NULL)
199 return (EBADF);
200 switch (SCARG(uap, cmd)) {
201
202 case F_DUPFD:
203 newmin = (long)SCARG(uap, arg);
204 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
205 (u_int)newmin >= maxfiles)
206 return (EINVAL);
207 if ((error = fdalloc(p, newmin, &i)) != 0)
208 return (error);
209 return (finishdup(fdp, fd, i, retval));
210
211 case F_GETFD:
212 *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
213 return (0);
214
215 case F_SETFD:
216 if ((long)SCARG(uap, arg) & 1)
217 fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
218 else
219 fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
220 return (0);
221
222 case F_GETFL:
223 *retval = OFLAGS(fp->f_flag);
224 return (0);
225
226 case F_SETFL:
227 fp->f_flag &= ~FCNTLFLAGS;
228 fp->f_flag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
229 tmp = fp->f_flag & FNONBLOCK;
230 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
231 if (error)
232 return (error);
233 tmp = fp->f_flag & FASYNC;
234 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
235 if (!error)
236 return (0);
237 fp->f_flag &= ~FNONBLOCK;
238 tmp = 0;
239 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
240 return (error);
241
242 case F_GETOWN:
243 if (fp->f_type == DTYPE_SOCKET) {
244 *retval = ((struct socket *)fp->f_data)->so_pgid;
245 return (0);
246 }
247 error = (*fp->f_ops->fo_ioctl)
248 (fp, TIOCGPGRP, (caddr_t)retval, p);
249 *retval = -*retval;
250 return (error);
251
252 case F_SETOWN:
253 if (fp->f_type == DTYPE_SOCKET) {
254 ((struct socket *)fp->f_data)->so_pgid =
255 (long)SCARG(uap, arg);
256 return (0);
257 }
258 if ((long)SCARG(uap, arg) <= 0) {
259 SCARG(uap, arg) = (void *)(-(long)SCARG(uap, arg));
260 } else {
261 struct proc *p1 = pfind((long)SCARG(uap, arg));
262 if (p1 == 0)
263 return (ESRCH);
264 SCARG(uap, arg) = (void *)(long)p1->p_pgrp->pg_id;
265 }
266 return ((*fp->f_ops->fo_ioctl)
267 (fp, TIOCSPGRP, (caddr_t)&SCARG(uap, arg), p));
268
269 case F_SETLKW:
270 flg |= F_WAIT;
271 /* Fall into F_SETLK */
272
273 case F_SETLK:
274 if (fp->f_type != DTYPE_VNODE)
275 return (EBADF);
276 vp = (struct vnode *)fp->f_data;
277 /* Copy in the lock structure */
278 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
279 sizeof(fl));
280 if (error)
281 return (error);
282 if (fl.l_whence == SEEK_CUR)
283 fl.l_start += fp->f_offset;
284 switch (fl.l_type) {
285 case F_RDLCK:
286 if ((fp->f_flag & FREAD) == 0)
287 return (EBADF);
288 p->p_flag |= P_ADVLOCK;
289 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
290
291 case F_WRLCK:
292 if ((fp->f_flag & FWRITE) == 0)
293 return (EBADF);
294 p->p_flag |= P_ADVLOCK;
295 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
296
297 case F_UNLCK:
298 return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
299 F_POSIX));
300
301 default:
302 return (EINVAL);
303 }
304
305 case F_GETLK:
306 if (fp->f_type != DTYPE_VNODE)
307 return (EBADF);
308 vp = (struct vnode *)fp->f_data;
309 /* Copy in the lock structure */
310 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
311 sizeof(fl));
312 if (error)
313 return (error);
314 if (fl.l_whence == SEEK_CUR)
315 fl.l_start += fp->f_offset;
316 if (fl.l_type != F_RDLCK &&
317 fl.l_type != F_WRLCK &&
318 fl.l_type != F_UNLCK)
319 return (EINVAL);
320 error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX);
321 if (error)
322 return (error);
323 return (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg),
324 sizeof(fl)));
325
326 default:
327 return (EINVAL);
328 }
329 /* NOTREACHED */
330 }
331
332 /*
333 * Common code for dup, dup2, and fcntl(F_DUPFD).
334 */
335 int
336 finishdup(fdp, old, new, retval)
337 register struct filedesc *fdp;
338 register int old, new;
339 register_t *retval;
340 {
341 register struct file *fp;
342
343 fp = fdp->fd_ofiles[old];
344 fdp->fd_ofiles[new] = fp;
345 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
346 fp->f_count++;
347 fd_used(fdp, new);
348 *retval = new;
349 return (0);
350 }
351
352 int
353 fdrelease(p, fd)
354 struct proc *p;
355 int fd;
356 {
357 register struct filedesc *fdp = p->p_fd;
358 register struct file **fpp, *fp;
359 register char *pf;
360
361 fpp = &fdp->fd_ofiles[fd];
362 fp = *fpp;
363 if (fp == NULL)
364 return (EBADF);
365 pf = &fdp->fd_ofileflags[fd];
366 #if defined(UVM)
367 if (*pf & UF_MAPPED) {
368 /* XXX: USELESS? XXXCDC check it */
369 p->p_fd->fd_ofileflags[fd] &= ~UF_MAPPED;
370 }
371 #else
372 if (*pf & UF_MAPPED)
373 (void) munmapfd(p, fd);
374 #endif
375 *fpp = NULL;
376 *pf = 0;
377 fd_unused(fdp, fd);
378 return (closef(fp, p));
379 }
380
381 /*
382 * Close a file descriptor.
383 */
384 /* ARGSUSED */
385 int
386 sys_close(p, v, retval)
387 struct proc *p;
388 void *v;
389 register_t *retval;
390 {
391 struct sys_close_args /* {
392 syscallarg(int) fd;
393 } */ *uap = v;
394 int fd = SCARG(uap, fd);
395 register struct filedesc *fdp = p->p_fd;
396
397 if ((u_int)fd >= fdp->fd_nfiles)
398 return (EBADF);
399 return (fdrelease(p, fd));
400 }
401
402 /*
403 * Return status information about a file descriptor.
404 */
405 /* ARGSUSED */
406 int
407 sys___fstat13(p, v, retval)
408 struct proc *p;
409 void *v;
410 register_t *retval;
411 {
412 register struct sys___fstat13_args /* {
413 syscallarg(int) fd;
414 syscallarg(struct stat *) sb;
415 } */ *uap = v;
416 int fd = SCARG(uap, fd);
417 register struct filedesc *fdp = p->p_fd;
418 register struct file *fp;
419 struct stat ub;
420 int error;
421
422 if ((u_int)fd >= fdp->fd_nfiles ||
423 (fp = fdp->fd_ofiles[fd]) == NULL)
424 return (EBADF);
425 switch (fp->f_type) {
426
427 case DTYPE_VNODE:
428 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
429 break;
430
431 case DTYPE_SOCKET:
432 error = soo_stat((struct socket *)fp->f_data, &ub);
433 break;
434
435 default:
436 panic("fstat");
437 /*NOTREACHED*/
438 }
439 if (error == 0)
440 error = copyout(&ub, SCARG(uap, sb), sizeof(ub));
441 return (error);
442 }
443
444 /*
445 * Return pathconf information about a file descriptor.
446 */
447 /* ARGSUSED */
448 int
449 sys_fpathconf(p, v, retval)
450 struct proc *p;
451 void *v;
452 register_t *retval;
453 {
454 register struct sys_fpathconf_args /* {
455 syscallarg(int) fd;
456 syscallarg(int) name;
457 } */ *uap = v;
458 int fd = SCARG(uap, fd);
459 struct filedesc *fdp = p->p_fd;
460 struct file *fp;
461 struct vnode *vp;
462
463 if ((u_int)fd >= fdp->fd_nfiles ||
464 (fp = fdp->fd_ofiles[fd]) == NULL)
465 return (EBADF);
466 switch (fp->f_type) {
467
468 case DTYPE_SOCKET:
469 if (SCARG(uap, name) != _PC_PIPE_BUF)
470 return (EINVAL);
471 *retval = PIPE_BUF;
472 return (0);
473
474 case DTYPE_VNODE:
475 vp = (struct vnode *)fp->f_data;
476 return (VOP_PATHCONF(vp, SCARG(uap, name), retval));
477
478 default:
479 panic("fpathconf");
480 }
481 /*NOTREACHED*/
482 }
483
484 /*
485 * Allocate a file descriptor for the process.
486 */
487 int fdexpand;
488
489 int
490 fdalloc(p, want, result)
491 struct proc *p;
492 int want;
493 int *result;
494 {
495 register struct filedesc *fdp = p->p_fd;
496 register int i;
497 int lim, last, nfiles;
498 struct file **newofile;
499 char *newofileflags;
500
501 /*
502 * Search for a free descriptor starting at the higher
503 * of want or fd_freefile. If that fails, consider
504 * expanding the ofile array.
505 */
506 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
507 for (;;) {
508 last = min(fdp->fd_nfiles, lim);
509 if ((i = want) < fdp->fd_freefile)
510 i = fdp->fd_freefile;
511 for (; i < last; i++) {
512 if (fdp->fd_ofiles[i] == NULL) {
513 fd_used(fdp, i);
514 if (want <= fdp->fd_freefile)
515 fdp->fd_freefile = i;
516 *result = i;
517 return (0);
518 }
519 }
520
521 /*
522 * No space in current array. Expand?
523 */
524 if (fdp->fd_nfiles >= lim)
525 return (EMFILE);
526 if (fdp->fd_nfiles < NDEXTENT)
527 nfiles = NDEXTENT;
528 else
529 nfiles = 2 * fdp->fd_nfiles;
530 MALLOC(newofile, struct file **, nfiles * OFILESIZE,
531 M_FILEDESC, M_WAITOK);
532 newofileflags = (char *) &newofile[nfiles];
533 /*
534 * Copy the existing ofile and ofileflags arrays
535 * and zero the new portion of each array.
536 */
537 bcopy(fdp->fd_ofiles, newofile,
538 (i = sizeof(struct file *) * fdp->fd_nfiles));
539 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
540 bcopy(fdp->fd_ofileflags, newofileflags,
541 (i = sizeof(char) * fdp->fd_nfiles));
542 bzero(newofileflags + i, nfiles * sizeof(char) - i);
543 if (fdp->fd_nfiles > NDFILE)
544 FREE(fdp->fd_ofiles, M_FILEDESC);
545 fdp->fd_ofiles = newofile;
546 fdp->fd_ofileflags = newofileflags;
547 fdp->fd_nfiles = nfiles;
548 fdexpand++;
549 }
550 }
551
552 /*
553 * Check to see whether n user file descriptors
554 * are available to the process p.
555 */
556 int
557 fdavail(p, n)
558 struct proc *p;
559 register int n;
560 {
561 register struct filedesc *fdp = p->p_fd;
562 register struct file **fpp;
563 register int i, lim;
564
565 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
566 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
567 return (1);
568 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
569 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
570 if (*fpp == NULL && --n <= 0)
571 return (1);
572 return (0);
573 }
574
575 /*
576 * Create a new open file structure and allocate
577 * a file decriptor for the process that refers to it.
578 */
579 int
580 falloc(p, resultfp, resultfd)
581 register struct proc *p;
582 struct file **resultfp;
583 int *resultfd;
584 {
585 register struct file *fp, *fq;
586 int error, i;
587
588 if ((error = fdalloc(p, 0, &i)) != 0)
589 return (error);
590 if (nfiles >= maxfiles) {
591 tablefull("file");
592 return (ENFILE);
593 }
594 /*
595 * Allocate a new file descriptor.
596 * If the process has file descriptor zero open, add to the list
597 * of open files at that point, otherwise put it at the front of
598 * the list of open files.
599 */
600 nfiles++;
601 MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
602 bzero(fp, sizeof(struct file));
603 if ((fq = p->p_fd->fd_ofiles[0]) != NULL) {
604 LIST_INSERT_AFTER(fq, fp, f_list);
605 } else {
606 LIST_INSERT_HEAD(&filehead, fp, f_list);
607 }
608 p->p_fd->fd_ofiles[i] = fp;
609 fp->f_count = 1;
610 fp->f_cred = p->p_ucred;
611 crhold(fp->f_cred);
612 if (resultfp)
613 *resultfp = fp;
614 if (resultfd)
615 *resultfd = i;
616 return (0);
617 }
618
619 /*
620 * Free a file descriptor.
621 */
622 void
623 ffree(fp)
624 register struct file *fp;
625 {
626 LIST_REMOVE(fp, f_list);
627 crfree(fp->f_cred);
628 #ifdef DIAGNOSTIC
629 fp->f_count = 0;
630 #endif
631 nfiles--;
632 FREE(fp, M_FILE);
633 }
634
635 /*
636 * Create an initial filedesc structure, using the same current and root
637 * directories as p.
638 */
639 struct filedesc *
640 fdinit(p)
641 struct proc *p;
642 {
643 struct filedesc0 *newfdp;
644 struct filedesc *fdp = p->p_fd;
645
646 MALLOC(newfdp, struct filedesc0 *, sizeof(struct filedesc0),
647 M_FILEDESC, M_WAITOK);
648 bzero(newfdp, sizeof(struct filedesc0));
649 newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
650 VREF(newfdp->fd_fd.fd_cdir);
651 newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
652 if (newfdp->fd_fd.fd_rdir)
653 VREF(newfdp->fd_fd.fd_rdir);
654
655 fdinit1(newfdp);
656
657 return (&newfdp->fd_fd);
658 }
659
660 /*
661 * Initialize a file descriptor table.
662 */
663 void
664 fdinit1(newfdp)
665 struct filedesc0 *newfdp;
666 {
667 extern int cmask; /* init_main.c */
668
669 newfdp->fd_fd.fd_refcnt = 1;
670 newfdp->fd_fd.fd_cmask = cmask;
671 newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
672 newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
673 newfdp->fd_fd.fd_nfiles = NDFILE;
674 }
675
676 /*
677 * Make p2 share p1's filedesc structure.
678 */
679 void
680 fdshare(p1, p2)
681 struct proc *p1, *p2;
682 {
683
684 p2->p_fd = p1->p_fd;
685 p1->p_fd->fd_refcnt++;
686 }
687
688 /*
689 * Make this process not share its filedesc structure, maintaining
690 * all file descriptor state.
691 */
692 void
693 fdunshare(p)
694 struct proc *p;
695 {
696 struct filedesc *newfd;
697
698 if (p->p_fd->fd_refcnt == 1)
699 return;
700
701 newfd = fdcopy(p);
702 fdfree(p);
703 p->p_fd = newfd;
704 }
705
706 /*
707 * Clear a process's fd table.
708 */
709 void
710 fdclear(p)
711 struct proc *p;
712 {
713 struct filedesc *newfd;
714
715 newfd = fdinit(p);
716 fdfree(p);
717 p->p_fd = newfd;
718 }
719
720 /*
721 * Copy a filedesc structure.
722 */
723 struct filedesc *
724 fdcopy(p)
725 struct proc *p;
726 {
727 register struct filedesc *newfdp, *fdp = p->p_fd;
728 register struct file **fpp;
729 register int i;
730
731 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
732 M_FILEDESC, M_WAITOK);
733 bcopy(fdp, newfdp, sizeof(struct filedesc));
734 VREF(newfdp->fd_cdir);
735 if (newfdp->fd_rdir)
736 VREF(newfdp->fd_rdir);
737 newfdp->fd_refcnt = 1;
738
739 /*
740 * If the number of open files fits in the internal arrays
741 * of the open file structure, use them, otherwise allocate
742 * additional memory for the number of descriptors currently
743 * in use.
744 */
745 if (newfdp->fd_lastfile < NDFILE) {
746 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
747 newfdp->fd_ofileflags =
748 ((struct filedesc0 *) newfdp)->fd_dfileflags;
749 i = NDFILE;
750 } else {
751 /*
752 * Compute the smallest multiple of NDEXTENT needed
753 * for the file descriptors currently in use,
754 * allowing the table to shrink.
755 */
756 i = newfdp->fd_nfiles;
757 while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
758 i /= 2;
759 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
760 M_FILEDESC, M_WAITOK);
761 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
762 }
763 newfdp->fd_nfiles = i;
764 bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
765 bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
766 fpp = newfdp->fd_ofiles;
767 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp++)
768 if (*fpp != NULL)
769 (*fpp)->f_count++;
770 return (newfdp);
771 }
772
773 /*
774 * Release a filedesc structure.
775 */
776 void
777 fdfree(p)
778 struct proc *p;
779 {
780 register struct filedesc *fdp = p->p_fd;
781 register struct file **fpp, *fp;
782 register int i;
783
784 if (--fdp->fd_refcnt > 0)
785 return;
786 fpp = fdp->fd_ofiles;
787 for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
788 fp = *fpp;
789 if (fp != NULL) {
790 *fpp = NULL;
791 (void) closef(fp, p);
792 }
793 }
794 p->p_fd = NULL;
795 if (fdp->fd_nfiles > NDFILE)
796 FREE(fdp->fd_ofiles, M_FILEDESC);
797 vrele(fdp->fd_cdir);
798 if (fdp->fd_rdir)
799 vrele(fdp->fd_rdir);
800 FREE(fdp, M_FILEDESC);
801 }
802
803 /*
804 * Internal form of close.
805 * Decrement reference count on file structure.
806 * Note: p may be NULL when closing a file
807 * that was being passed in a message.
808 */
809 int
810 closef(fp, p)
811 register struct file *fp;
812 register struct proc *p;
813 {
814 struct vnode *vp;
815 struct flock lf;
816 int error;
817
818 if (fp == NULL)
819 return (0);
820 /*
821 * POSIX record locking dictates that any close releases ALL
822 * locks owned by this process. This is handled by setting
823 * a flag in the unlock to free ONLY locks obeying POSIX
824 * semantics, and not to free BSD-style file locks.
825 * If the descriptor was in a message, POSIX-style locks
826 * aren't passed with the descriptor.
827 */
828 if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
829 lf.l_whence = SEEK_SET;
830 lf.l_start = 0;
831 lf.l_len = 0;
832 lf.l_type = F_UNLCK;
833 vp = (struct vnode *)fp->f_data;
834 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
835 }
836 if (--fp->f_count > 0)
837 return (0);
838 if (fp->f_count < 0)
839 panic("closef: count < 0");
840 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
841 lf.l_whence = SEEK_SET;
842 lf.l_start = 0;
843 lf.l_len = 0;
844 lf.l_type = F_UNLCK;
845 vp = (struct vnode *)fp->f_data;
846 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
847 }
848 if (fp->f_ops)
849 error = (*fp->f_ops->fo_close)(fp, p);
850 else
851 error = 0;
852 ffree(fp);
853 return (error);
854 }
855
856 /*
857 * Apply an advisory lock on a file descriptor.
858 *
859 * Just attempt to get a record lock of the requested type on
860 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
861 */
862 /* ARGSUSED */
863 int
864 sys_flock(p, v, retval)
865 struct proc *p;
866 void *v;
867 register_t *retval;
868 {
869 register struct sys_flock_args /* {
870 syscallarg(int) fd;
871 syscallarg(int) how;
872 } */ *uap = v;
873 int fd = SCARG(uap, fd);
874 int how = SCARG(uap, how);
875 register struct filedesc *fdp = p->p_fd;
876 register struct file *fp;
877 struct vnode *vp;
878 struct flock lf;
879
880 if ((u_int)fd >= fdp->fd_nfiles ||
881 (fp = fdp->fd_ofiles[fd]) == NULL)
882 return (EBADF);
883 if (fp->f_type != DTYPE_VNODE)
884 return (EOPNOTSUPP);
885 vp = (struct vnode *)fp->f_data;
886 lf.l_whence = SEEK_SET;
887 lf.l_start = 0;
888 lf.l_len = 0;
889 if (how & LOCK_UN) {
890 lf.l_type = F_UNLCK;
891 fp->f_flag &= ~FHASLOCK;
892 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
893 }
894 if (how & LOCK_EX)
895 lf.l_type = F_WRLCK;
896 else if (how & LOCK_SH)
897 lf.l_type = F_RDLCK;
898 else
899 return (EINVAL);
900 fp->f_flag |= FHASLOCK;
901 if (how & LOCK_NB)
902 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
903 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
904 }
905
906 /*
907 * File Descriptor pseudo-device driver (/dev/fd/).
908 *
909 * Opening minor device N dup()s the file (if any) connected to file
910 * descriptor N belonging to the calling process. Note that this driver
911 * consists of only the ``open()'' routine, because all subsequent
912 * references to this file will be direct to the other driver.
913 */
914 /* ARGSUSED */
915 int
916 filedescopen(dev, mode, type, p)
917 dev_t dev;
918 int mode, type;
919 struct proc *p;
920 {
921
922 /*
923 * XXX Kludge: set curproc->p_dupfd to contain the value of the
924 * the file descriptor being sought for duplication. The error
925 * return ensures that the vnode for this device will be released
926 * by vn_open. Open will detect this special error and take the
927 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
928 * will simply report the error.
929 */
930 p->p_dupfd = minor(dev);
931 return (ENODEV);
932 }
933
934 /*
935 * Duplicate the specified descriptor to a free descriptor.
936 */
937 int
938 dupfdopen(fdp, indx, dfd, mode, error)
939 register struct filedesc *fdp;
940 register int indx, dfd;
941 int mode;
942 int error;
943 {
944 register struct file *wfp;
945 struct file *fp;
946
947 /*
948 * If the to-be-dup'd fd number is greater than the allowed number
949 * of file descriptors, or the fd to be dup'd has already been
950 * closed, reject. Note, check for new == old is necessary as
951 * falloc could allocate an already closed to-be-dup'd descriptor
952 * as the new descriptor.
953 */
954 fp = fdp->fd_ofiles[indx];
955 if ((u_int)dfd >= fdp->fd_nfiles ||
956 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
957 return (EBADF);
958
959 /*
960 * There are two cases of interest here.
961 *
962 * For ENODEV simply dup (dfd) to file descriptor
963 * (indx) and return.
964 *
965 * For ENXIO steal away the file structure from (dfd) and
966 * store it in (indx). (dfd) is effectively closed by
967 * this operation.
968 *
969 * Any other error code is just returned.
970 */
971 switch (error) {
972 case ENODEV:
973 /*
974 * Check that the mode the file is being opened for is a
975 * subset of the mode of the existing descriptor.
976 */
977 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
978 return (EACCES);
979 fdp->fd_ofiles[indx] = wfp;
980 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
981 wfp->f_count++;
982 fd_used(fdp, indx);
983 return (0);
984
985 case ENXIO:
986 /*
987 * Steal away the file pointer from dfd, and stuff it into indx.
988 */
989 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
990 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
991 fdp->fd_ofiles[dfd] = NULL;
992 fdp->fd_ofileflags[dfd] = 0;
993 /*
994 * Complete the clean up of the filedesc structure by
995 * recomputing the various hints.
996 */
997 fd_used(fdp, indx);
998 fd_unused(fdp, dfd);
999 return (0);
1000
1001 default:
1002 return (error);
1003 }
1004 /* NOTREACHED */
1005 }
1006
1007 /*
1008 * Close any files on exec?
1009 */
1010 void
1011 fdcloseexec(p)
1012 struct proc *p;
1013 {
1014 register struct filedesc *fdp = p->p_fd;
1015 register int fd;
1016
1017 for (fd = 0; fd <= fdp->fd_lastfile; fd++)
1018 if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
1019 (void) fdrelease(p, fd);
1020 }
1021