kern_descrip.c revision 1.79.2.8 1 /* $NetBSD: kern_descrip.c,v 1.79.2.8 2002/09/06 08:47:45 jdolecek 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 <sys/cdefs.h>
44 __KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.79.2.8 2002/09/06 08:47:45 jdolecek Exp $");
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/filedesc.h>
49 #include <sys/kernel.h>
50 #include <sys/vnode.h>
51 #include <sys/proc.h>
52 #include <sys/file.h>
53 #include <sys/namei.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
56 #include <sys/stat.h>
57 #include <sys/ioctl.h>
58 #include <sys/fcntl.h>
59 #include <sys/malloc.h>
60 #include <sys/pool.h>
61 #include <sys/syslog.h>
62 #include <sys/unistd.h>
63 #include <sys/resourcevar.h>
64 #include <sys/conf.h>
65 #include <sys/event.h>
66
67 #include <sys/mount.h>
68 #include <sys/syscallargs.h>
69
70 /*
71 * Descriptor management.
72 */
73 struct filelist filehead; /* head of list of open files */
74 int nfiles; /* actual number of open files */
75 struct pool file_pool; /* memory pool for file structures */
76 struct pool cwdi_pool; /* memory pool for cwdinfo structures */
77 struct pool filedesc0_pool; /* memory pool for filedesc0 structures */
78
79 static __inline void fd_used(struct filedesc *, int);
80 static __inline void fd_unused(struct filedesc *, int);
81 int finishdup(struct proc *, int, int, register_t *);
82 int fcntl_forfs(int, struct proc *, int, void *);
83
84 static __inline void
85 fd_used(struct filedesc *fdp, int fd)
86 {
87
88 if (fd > fdp->fd_lastfile)
89 fdp->fd_lastfile = fd;
90 }
91
92 static __inline void
93 fd_unused(struct filedesc *fdp, int fd)
94 {
95
96 if (fd < fdp->fd_freefile)
97 fdp->fd_freefile = fd;
98 #ifdef DIAGNOSTIC
99 if (fd > fdp->fd_lastfile)
100 panic("fd_unused: fd_lastfile inconsistent");
101 #endif
102 if (fd == fdp->fd_lastfile) {
103 do {
104 fd--;
105 } while (fd >= 0 && fdp->fd_ofiles[fd] == NULL);
106 fdp->fd_lastfile = fd;
107 }
108 }
109
110 struct file *
111 fd_getfile(struct filedesc *fdp, int fd)
112 {
113 struct file *fp;
114
115 if ((u_int) fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
116 return (NULL);
117
118 if (FILE_IS_USABLE(fp) == 0)
119 return (NULL);
120
121 return (fp);
122 }
123
124 /*
125 * System calls on descriptors.
126 */
127
128 /*
129 * Duplicate a file descriptor.
130 */
131 /* ARGSUSED */
132 int
133 sys_dup(struct proc *p, void *v, register_t *retval)
134 {
135 struct sys_dup_args /* {
136 syscallarg(int) fd;
137 } */ *uap = v;
138 struct file *fp;
139 struct filedesc *fdp;
140 int old, new, error;
141
142 fdp = p->p_fd;
143 old = SCARG(uap, fd);
144
145 restart:
146 if ((fp = fd_getfile(fdp, old)) == NULL)
147 return (EBADF);
148
149 FILE_USE(fp);
150
151 if ((error = fdalloc(p, 0, &new)) != 0) {
152 if (error == ENOSPC) {
153 fdexpand(p);
154 FILE_UNUSE(fp, p);
155 goto restart;
156 }
157 FILE_UNUSE(fp, p);
158 return (error);
159 }
160
161 /* finishdup() will unuse the descriptors for us */
162 return (finishdup(p, old, new, retval));
163 }
164
165 /*
166 * Duplicate a file descriptor to a particular value.
167 */
168 /* ARGSUSED */
169 int
170 sys_dup2(struct proc *p, void *v, register_t *retval)
171 {
172 struct sys_dup2_args /* {
173 syscallarg(int) from;
174 syscallarg(int) to;
175 } */ *uap = v;
176 struct file *fp;
177 struct filedesc *fdp;
178 int old, new, i, error;
179
180 fdp = p->p_fd;
181 old = SCARG(uap, from);
182 new = SCARG(uap, to);
183
184 restart:
185 if ((fp = fd_getfile(fdp, old)) == NULL)
186 return (EBADF);
187
188 if ((u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
189 (u_int)new >= maxfiles)
190 return (EBADF);
191
192 if (old == new) {
193 *retval = new;
194 return (0);
195 }
196
197 FILE_USE(fp);
198
199 if (new >= fdp->fd_nfiles) {
200 if ((error = fdalloc(p, new, &i)) != 0) {
201 if (error == ENOSPC) {
202 fdexpand(p);
203 FILE_UNUSE(fp, p);
204 goto restart;
205 }
206 FILE_UNUSE(fp, p);
207 return (error);
208 }
209 if (new != i)
210 panic("dup2: fdalloc");
211 }
212
213 /*
214 * finishdup() will close the file that's in the `new'
215 * slot, if there's one there.
216 */
217
218 /* finishdup() will unuse the descriptors for us */
219 return (finishdup(p, old, new, retval));
220 }
221
222 /*
223 * The file control system call.
224 */
225 /* ARGSUSED */
226 int
227 sys_fcntl(struct proc *p, void *v, register_t *retval)
228 {
229 struct sys_fcntl_args /* {
230 syscallarg(int) fd;
231 syscallarg(int) cmd;
232 syscallarg(void *) arg;
233 } */ *uap = v;
234 struct filedesc *fdp;
235 struct file *fp;
236 struct vnode *vp;
237 int fd, i, tmp, error, flg, cmd, newmin;
238 struct flock fl;
239
240 fd = SCARG(uap, fd);
241 fdp = p->p_fd;
242 error = 0;
243 flg = F_POSIX;
244
245 restart:
246 if ((fp = fd_getfile(fdp, fd)) == NULL)
247 return (EBADF);
248
249 FILE_USE(fp);
250
251 cmd = SCARG(uap, cmd);
252 if ((cmd & F_FSCTL)) {
253 error = fcntl_forfs(fd, p, cmd, SCARG(uap, arg));
254 goto out;
255 }
256
257 switch (cmd) {
258
259 case F_DUPFD:
260 newmin = (long)SCARG(uap, arg);
261 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
262 (u_int)newmin >= maxfiles) {
263 error = EINVAL;
264 goto out;
265 }
266 if ((error = fdalloc(p, newmin, &i)) != 0) {
267 if (error == ENOSPC) {
268 fdexpand(p);
269 FILE_UNUSE(fp, p);
270 goto restart;
271 }
272 goto out;
273 }
274
275 /* finishdup() will unuse the descriptors for us */
276 return (finishdup(p, fd, i, retval));
277
278 case F_GETFD:
279 *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
280 break;
281
282 case F_SETFD:
283 if ((long)SCARG(uap, arg) & 1)
284 fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
285 else
286 fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
287 break;
288
289 case F_GETFL:
290 *retval = OFLAGS(fp->f_flag);
291 break;
292
293 case F_SETFL:
294 tmp = FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
295 error = (*fp->f_ops->fo_fcntl)(fp, F_SETFL, (caddr_t)&tmp, p);
296 if (error)
297 goto out;
298 fp->f_flag &= ~FCNTLFLAGS;
299 fp->f_flag |= tmp;
300 tmp = fp->f_flag & FNONBLOCK;
301 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
302 if (error)
303 goto out;
304 tmp = fp->f_flag & FASYNC;
305 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
306 if (error == 0)
307 goto out;
308 fp->f_flag &= ~FNONBLOCK;
309 tmp = 0;
310 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
311 break;
312
313 case F_GETOWN:
314 if (fp->f_type == DTYPE_SOCKET) {
315 *retval = ((struct socket *)fp->f_data)->so_pgid;
316 goto out;
317 }
318 error = (*fp->f_ops->fo_ioctl)
319 (fp, TIOCGPGRP, (caddr_t)&tmp, p);
320 *retval = -tmp;
321 break;
322
323 case F_SETOWN:
324 if (fp->f_type == DTYPE_SOCKET) {
325 ((struct socket *)fp->f_data)->so_pgid =
326 (long)SCARG(uap, arg);
327 goto out;
328 }
329 if ((long)SCARG(uap, arg) <= 0) {
330 tmp = (-(long)SCARG(uap, arg));
331 } else {
332 struct proc *p1 = pfind((long)SCARG(uap, arg));
333 if (p1 == 0) {
334 error = ESRCH;
335 goto out;
336 }
337 tmp = (long)p1->p_pgrp->pg_id;
338 }
339 error = (*fp->f_ops->fo_ioctl)
340 (fp, TIOCSPGRP, (caddr_t)&tmp, p);
341 break;
342
343 case F_SETLKW:
344 flg |= F_WAIT;
345 /* Fall into F_SETLK */
346
347 case F_SETLK:
348 if (fp->f_type != DTYPE_VNODE) {
349 error = EINVAL;
350 goto out;
351 }
352 vp = (struct vnode *)fp->f_data;
353 /* Copy in the lock structure */
354 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
355 sizeof(fl));
356 if (error)
357 goto out;
358 if (fl.l_whence == SEEK_CUR)
359 fl.l_start += fp->f_offset;
360 switch (fl.l_type) {
361 case F_RDLCK:
362 if ((fp->f_flag & FREAD) == 0) {
363 error = EBADF;
364 goto out;
365 }
366 p->p_flag |= P_ADVLOCK;
367 error = VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg);
368 goto out;
369
370 case F_WRLCK:
371 if ((fp->f_flag & FWRITE) == 0) {
372 error = EBADF;
373 goto out;
374 }
375 p->p_flag |= P_ADVLOCK;
376 error = VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg);
377 goto out;
378
379 case F_UNLCK:
380 error = VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
381 F_POSIX);
382 goto out;
383
384 default:
385 error = EINVAL;
386 goto out;
387 }
388
389 case F_GETLK:
390 if (fp->f_type != DTYPE_VNODE) {
391 error = EINVAL;
392 goto out;
393 }
394 vp = (struct vnode *)fp->f_data;
395 /* Copy in the lock structure */
396 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
397 sizeof(fl));
398 if (error)
399 goto out;
400 if (fl.l_whence == SEEK_CUR)
401 fl.l_start += fp->f_offset;
402 if (fl.l_type != F_RDLCK &&
403 fl.l_type != F_WRLCK &&
404 fl.l_type != F_UNLCK) {
405 error = EINVAL;
406 goto out;
407 }
408 error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX);
409 if (error)
410 goto out;
411 error = copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg),
412 sizeof(fl));
413 break;
414
415 default:
416 error = EINVAL;
417 }
418
419 out:
420 FILE_UNUSE(fp, p);
421 return (error);
422 }
423
424 /*
425 * Common code for dup, dup2, and fcntl(F_DUPFD).
426 */
427 int
428 finishdup(struct proc *p, int old, int new, register_t *retval)
429 {
430 struct filedesc *fdp;
431 struct file *fp, *delfp;
432
433 fdp = p->p_fd;
434
435 /*
436 * If there is a file in the new slot, remember it so we
437 * can close it after we've finished the dup. We need
438 * to do it after the dup is finished, since closing
439 * the file may block.
440 *
441 * Note: `old' is already used for us.
442 */
443 delfp = fdp->fd_ofiles[new];
444
445 fp = fdp->fd_ofiles[old];
446 fdp->fd_ofiles[new] = fp;
447 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
448 fp->f_count++;
449 /*
450 * Note, don't have to mark it "used" in the table if there
451 * was already a file in the `new' slot.
452 */
453 if (delfp == NULL)
454 fd_used(fdp, new);
455 *retval = new;
456 FILE_UNUSE(fp, p);
457
458 if (delfp != NULL) {
459 FILE_USE(delfp);
460 /* XXXLUKEM jdolecek: knote_fdclose() call needed */
461 (void) closef(delfp, p);
462 }
463 return (0);
464 }
465
466 void
467 fdremove(struct filedesc *fdp, int fd)
468 {
469
470 fdp->fd_ofiles[fd] = NULL;
471 fd_unused(fdp, fd);
472 }
473
474 int
475 fdrelease(struct proc *p, int fd)
476 {
477 struct filedesc *fdp;
478 struct file **fpp, *fp;
479
480 fdp = p->p_fd;
481 fpp = &fdp->fd_ofiles[fd];
482 fp = *fpp;
483 if (fp == NULL)
484 return (EBADF);
485
486 FILE_USE(fp);
487
488 *fpp = NULL;
489 fdp->fd_ofileflags[fd] = 0;
490 if (fd < fdp->fd_knlistsize)
491 knote_fdclose(p, fd);
492 fd_unused(fdp, fd);
493 return (closef(fp, p));
494 }
495
496 /*
497 * Close a file descriptor.
498 */
499 /* ARGSUSED */
500 int
501 sys_close(struct proc *p, void *v, register_t *retval)
502 {
503 struct sys_close_args /* {
504 syscallarg(int) fd;
505 } */ *uap = v;
506 int fd;
507 struct filedesc *fdp;
508 struct file *fp;
509
510 fd = SCARG(uap, fd);
511 fdp = p->p_fd;
512
513 if ((fp = fd_getfile(fdp, fd)) == NULL)
514 return (EBADF);
515
516 return (fdrelease(p, fd));
517 }
518
519 /*
520 * Return status information about a file descriptor.
521 */
522 /* ARGSUSED */
523 int
524 sys___fstat13(struct proc *p, void *v, register_t *retval)
525 {
526 struct sys___fstat13_args /* {
527 syscallarg(int) fd;
528 syscallarg(struct stat *) sb;
529 } */ *uap = v;
530 int fd;
531 struct filedesc *fdp;
532 struct file *fp;
533 struct stat ub;
534 int error;
535
536 fd = SCARG(uap, fd);
537 fdp = p->p_fd;
538
539 if ((fp = fd_getfile(fdp, fd)) == NULL)
540 return (EBADF);
541
542 FILE_USE(fp);
543 error = (*fp->f_ops->fo_stat)(fp, &ub, p);
544 FILE_UNUSE(fp, p);
545
546 if (error == 0)
547 error = copyout(&ub, SCARG(uap, sb), sizeof(ub));
548
549 return (error);
550 }
551
552 /*
553 * Return pathconf information about a file descriptor.
554 */
555 /* ARGSUSED */
556 int
557 sys_fpathconf(struct proc *p, void *v, register_t *retval)
558 {
559 struct sys_fpathconf_args /* {
560 syscallarg(int) fd;
561 syscallarg(int) name;
562 } */ *uap = v;
563 int fd;
564 struct filedesc *fdp;
565 struct file *fp;
566 struct vnode *vp;
567 int error;
568
569 fd = SCARG(uap, fd);
570 fdp = p->p_fd;
571 error = 0;
572
573 if ((fp = fd_getfile(fdp, fd)) == NULL)
574 return (EBADF);
575
576 FILE_USE(fp);
577
578 switch (fp->f_type) {
579
580 case DTYPE_SOCKET:
581 case DTYPE_PIPE:
582 if (SCARG(uap, name) != _PC_PIPE_BUF)
583 error = EINVAL;
584 else
585 *retval = PIPE_BUF;
586 break;
587
588 case DTYPE_VNODE:
589 vp = (struct vnode *)fp->f_data;
590 error = VOP_PATHCONF(vp, SCARG(uap, name), retval);
591 break;
592
593 case DTYPE_KQUEUE:
594 error = EINVAL;
595 break;
596 default:
597 error = EOPNOTSUPP;
598 break;
599 }
600
601 FILE_UNUSE(fp, p);
602 return (error);
603 }
604
605 /*
606 * Allocate a file descriptor for the process.
607 */
608 int fdexpanded; /* XXX: what else uses this? */
609
610 int
611 fdalloc(struct proc *p, int want, int *result)
612 {
613 struct filedesc *fdp;
614 int i, lim, last;
615
616 fdp = p->p_fd;
617
618 /*
619 * Search for a free descriptor starting at the higher
620 * of want or fd_freefile. If that fails, consider
621 * expanding the ofile array.
622 */
623 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
624 last = min(fdp->fd_nfiles, lim);
625 if ((i = want) < fdp->fd_freefile)
626 i = fdp->fd_freefile;
627 for (; i < last; i++) {
628 if (fdp->fd_ofiles[i] == NULL) {
629 fd_used(fdp, i);
630 if (want <= fdp->fd_freefile)
631 fdp->fd_freefile = i;
632 *result = i;
633 return (0);
634 }
635 }
636
637 /* No space in current array. Expand? */
638 if (fdp->fd_nfiles >= lim)
639 return (EMFILE);
640
641 /* Let the caller do it. */
642 return (ENOSPC);
643 }
644
645 void
646 fdexpand(struct proc *p)
647 {
648 struct filedesc *fdp;
649 int i, nfiles;
650 struct file **newofile;
651 char *newofileflags;
652
653 fdp = p->p_fd;
654
655 if (fdp->fd_nfiles < NDEXTENT)
656 nfiles = NDEXTENT;
657 else
658 nfiles = 2 * fdp->fd_nfiles;
659 newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK);
660 newofileflags = (char *) &newofile[nfiles];
661 /*
662 * Copy the existing ofile and ofileflags arrays
663 * and zero the new portion of each array.
664 */
665 memcpy(newofile, fdp->fd_ofiles,
666 (i = sizeof(struct file *) * fdp->fd_nfiles));
667 memset((char *)newofile + i, 0,
668 nfiles * sizeof(struct file *) - i);
669 memcpy(newofileflags, fdp->fd_ofileflags,
670 (i = sizeof(char) * fdp->fd_nfiles));
671 memset(newofileflags + i, 0, nfiles * sizeof(char) - i);
672 if (fdp->fd_nfiles > NDFILE)
673 free(fdp->fd_ofiles, M_FILEDESC);
674 fdp->fd_ofiles = newofile;
675 fdp->fd_ofileflags = newofileflags;
676 fdp->fd_nfiles = nfiles;
677 fdexpanded++;
678 }
679
680 /*
681 * Check to see whether n user file descriptors
682 * are available to the process p.
683 */
684 int
685 fdavail(struct proc *p, int n)
686 {
687 struct filedesc *fdp;
688 struct file **fpp;
689 int i, lim;
690
691 fdp = p->p_fd;
692 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
693 if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
694 return (1);
695 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
696 for (i = min(lim,fdp->fd_nfiles) - fdp->fd_freefile; --i >= 0; fpp++)
697 if (*fpp == NULL && --n <= 0)
698 return (1);
699 return (0);
700 }
701
702 /*
703 * Initialize the data structures necessary for managing files.
704 */
705 void
706 finit(void)
707 {
708
709 pool_init(&file_pool, sizeof(struct file), 0, 0, 0, "filepl",
710 &pool_allocator_nointr);
711 pool_init(&cwdi_pool, sizeof(struct cwdinfo), 0, 0, 0, "cwdipl",
712 &pool_allocator_nointr);
713 pool_init(&filedesc0_pool, sizeof(struct filedesc0), 0, 0, 0, "fdescpl",
714 &pool_allocator_nointr);
715 }
716
717 /*
718 * Create a new open file structure and allocate
719 * a file decriptor for the process that refers to it.
720 */
721 int
722 falloc(struct proc *p, struct file **resultfp, int *resultfd)
723 {
724 struct file *fp, *fq;
725 int error, i;
726
727 restart:
728 if ((error = fdalloc(p, 0, &i)) != 0) {
729 if (error == ENOSPC) {
730 fdexpand(p);
731 goto restart;
732 }
733 return (error);
734 }
735 if (nfiles >= maxfiles) {
736 tablefull("file", "increase kern.maxfiles or MAXFILES");
737 return (ENFILE);
738 }
739 /*
740 * Allocate a new file descriptor.
741 * If the process has file descriptor zero open, add to the list
742 * of open files at that point, otherwise put it at the front of
743 * the list of open files.
744 */
745 nfiles++;
746 fp = pool_get(&file_pool, PR_WAITOK);
747 memset(fp, 0, sizeof(struct file));
748 fp->f_iflags = FIF_LARVAL;
749 if ((fq = p->p_fd->fd_ofiles[0]) != NULL) {
750 LIST_INSERT_AFTER(fq, fp, f_list);
751 } else {
752 LIST_INSERT_HEAD(&filehead, fp, f_list);
753 }
754 p->p_fd->fd_ofiles[i] = fp;
755 fp->f_count = 1;
756 fp->f_cred = p->p_ucred;
757 crhold(fp->f_cred);
758 if (resultfp) {
759 FILE_USE(fp);
760 *resultfp = fp;
761 }
762 if (resultfd)
763 *resultfd = i;
764 return (0);
765 }
766
767 /*
768 * Free a file descriptor.
769 */
770 void
771 ffree(struct file *fp)
772 {
773
774 #ifdef DIAGNOSTIC
775 if (fp->f_usecount)
776 panic("ffree");
777 #endif
778
779 LIST_REMOVE(fp, f_list);
780 crfree(fp->f_cred);
781 #ifdef DIAGNOSTIC
782 fp->f_count = 0;
783 #endif
784 nfiles--;
785 pool_put(&file_pool, fp);
786 }
787
788 /*
789 * Create an initial cwdinfo structure, using the same current and root
790 * directories as p.
791 */
792 struct cwdinfo *
793 cwdinit(struct proc *p)
794 {
795 struct cwdinfo *cwdi;
796
797 cwdi = pool_get(&cwdi_pool, PR_WAITOK);
798
799 cwdi->cwdi_cdir = p->p_cwdi->cwdi_cdir;
800 if (cwdi->cwdi_cdir)
801 VREF(cwdi->cwdi_cdir);
802 cwdi->cwdi_rdir = p->p_cwdi->cwdi_rdir;
803 if (cwdi->cwdi_rdir)
804 VREF(cwdi->cwdi_rdir);
805 cwdi->cwdi_cmask = p->p_cwdi->cwdi_cmask;
806 cwdi->cwdi_refcnt = 1;
807
808 return (cwdi);
809 }
810
811 /*
812 * Make p2 share p1's cwdinfo.
813 */
814 void
815 cwdshare(struct proc *p1, struct proc *p2)
816 {
817
818 p2->p_cwdi = p1->p_cwdi;
819 p1->p_cwdi->cwdi_refcnt++;
820 }
821
822 /*
823 * Make this process not share its cwdinfo structure, maintaining
824 * all cwdinfo state.
825 */
826 void
827 cwdunshare(struct proc *p)
828 {
829 struct cwdinfo *newcwdi;
830
831 if (p->p_cwdi->cwdi_refcnt == 1)
832 return;
833
834 newcwdi = cwdinit(p);
835 cwdfree(p);
836 p->p_cwdi = newcwdi;
837 }
838
839 /*
840 * Release a cwdinfo structure.
841 */
842 void
843 cwdfree(struct proc *p)
844 {
845 struct cwdinfo *cwdi;
846
847 cwdi = p->p_cwdi;
848 if (--cwdi->cwdi_refcnt > 0)
849 return;
850
851 p->p_cwdi = NULL;
852
853 vrele(cwdi->cwdi_cdir);
854 if (cwdi->cwdi_rdir)
855 vrele(cwdi->cwdi_rdir);
856 pool_put(&cwdi_pool, cwdi);
857 }
858
859 /*
860 * Create an initial filedesc structure, using the same current and root
861 * directories as p.
862 */
863 struct filedesc *
864 fdinit(struct proc *p)
865 {
866 struct filedesc0 *newfdp;
867
868 newfdp = pool_get(&filedesc0_pool, PR_WAITOK);
869 memset(newfdp, 0, sizeof(struct filedesc0));
870
871 fdinit1(newfdp);
872
873 return (&newfdp->fd_fd);
874 }
875
876 /*
877 * Initialize a file descriptor table.
878 */
879 void
880 fdinit1(struct filedesc0 *newfdp)
881 {
882
883 newfdp->fd_fd.fd_refcnt = 1;
884 newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
885 newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
886 newfdp->fd_fd.fd_nfiles = NDFILE;
887 newfdp->fd_fd.fd_knlistsize = -1;
888 }
889
890 /*
891 * Make p2 share p1's filedesc structure.
892 */
893 void
894 fdshare(struct proc *p1, struct proc *p2)
895 {
896
897 p2->p_fd = p1->p_fd;
898 p1->p_fd->fd_refcnt++;
899 }
900
901 /*
902 * Make this process not share its filedesc structure, maintaining
903 * all file descriptor state.
904 */
905 void
906 fdunshare(struct proc *p)
907 {
908 struct filedesc *newfd;
909
910 if (p->p_fd->fd_refcnt == 1)
911 return;
912
913 newfd = fdcopy(p);
914 fdfree(p);
915 p->p_fd = newfd;
916 }
917
918 /*
919 * Clear a process's fd table.
920 */
921 void
922 fdclear(struct proc *p)
923 {
924 struct filedesc *newfd;
925
926 newfd = fdinit(p);
927 fdfree(p);
928 p->p_fd = newfd;
929 }
930
931 /*
932 * Copy a filedesc structure.
933 */
934 struct filedesc *
935 fdcopy(struct proc *p)
936 {
937 struct filedesc *newfdp, *fdp;
938 struct file **fpp;
939 int i;
940
941 fdp = p->p_fd;
942 newfdp = pool_get(&filedesc0_pool, PR_WAITOK);
943 memcpy(newfdp, fdp, sizeof(struct filedesc));
944 newfdp->fd_refcnt = 1;
945
946 /*
947 * If the number of open files fits in the internal arrays
948 * of the open file structure, use them, otherwise allocate
949 * additional memory for the number of descriptors currently
950 * in use.
951 */
952 if (newfdp->fd_lastfile < NDFILE) {
953 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
954 newfdp->fd_ofileflags =
955 ((struct filedesc0 *) newfdp)->fd_dfileflags;
956 i = NDFILE;
957 } else {
958 /*
959 * Compute the smallest multiple of NDEXTENT needed
960 * for the file descriptors currently in use,
961 * allowing the table to shrink.
962 */
963 i = newfdp->fd_nfiles;
964 while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
965 i /= 2;
966 newfdp->fd_ofiles = malloc(i * OFILESIZE, M_FILEDESC, M_WAITOK);
967 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
968 }
969 newfdp->fd_nfiles = i;
970 memcpy(newfdp->fd_ofiles, fdp->fd_ofiles, i * sizeof(struct file **));
971 memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags, i * sizeof(char));
972 /*
973 * kq descriptors cannot be copied.
974 */
975 if (newfdp->fd_knlistsize != -1) {
976 fpp = newfdp->fd_ofiles;
977 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++) {
978 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE)
979 *fpp = NULL;
980 }
981 newfdp->fd_knlist = NULL;
982 newfdp->fd_knlistsize = -1;
983 newfdp->fd_knhash = NULL;
984 newfdp->fd_knhashmask = 0;
985 }
986 fpp = newfdp->fd_ofiles;
987 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp++)
988 if (*fpp != NULL)
989 (*fpp)->f_count++;
990 return (newfdp);
991 }
992
993 /*
994 * Release a filedesc structure.
995 */
996 void
997 fdfree(struct proc *p)
998 {
999 struct filedesc *fdp;
1000 struct file **fpp, *fp;
1001 int i;
1002
1003 fdp = p->p_fd;
1004 if (--fdp->fd_refcnt > 0)
1005 return;
1006 fpp = fdp->fd_ofiles;
1007 for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
1008 fp = *fpp;
1009 if (fp != NULL) {
1010 *fpp = NULL;
1011 FILE_USE(fp);
1012 if (i < fdp->fd_knlistsize)
1013 knote_fdclose(p, fdp->fd_lastfile - i);
1014 (void) closef(fp, p);
1015 }
1016 }
1017 p->p_fd = NULL;
1018 if (fdp->fd_nfiles > NDFILE)
1019 free(fdp->fd_ofiles, M_FILEDESC);
1020 if (fdp->fd_knlist)
1021 free(fdp->fd_knlist, M_KEVENT);
1022 if (fdp->fd_knhash)
1023 hashdone(fdp->fd_knhash, M_KEVENT);
1024 pool_put(&filedesc0_pool, fdp);
1025 }
1026
1027 /*
1028 * Internal form of close.
1029 * Decrement reference count on file structure.
1030 * Note: p may be NULL when closing a file
1031 * that was being passed in a message.
1032 *
1033 * Note: we expect the caller is holding a usecount, and expects us
1034 * to drop it (the caller thinks the file is going away forever).
1035 */
1036 int
1037 closef(struct file *fp, struct proc *p)
1038 {
1039 struct vnode *vp;
1040 struct flock lf;
1041 int error;
1042
1043 if (fp == NULL)
1044 return (0);
1045
1046 /*
1047 * POSIX record locking dictates that any close releases ALL
1048 * locks owned by this process. This is handled by setting
1049 * a flag in the unlock to free ONLY locks obeying POSIX
1050 * semantics, and not to free BSD-style file locks.
1051 * If the descriptor was in a message, POSIX-style locks
1052 * aren't passed with the descriptor.
1053 */
1054 if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
1055 lf.l_whence = SEEK_SET;
1056 lf.l_start = 0;
1057 lf.l_len = 0;
1058 lf.l_type = F_UNLCK;
1059 vp = (struct vnode *)fp->f_data;
1060 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
1061 }
1062
1063 /*
1064 * If WANTCLOSE is set, then the reference count on the file
1065 * is 0, but there were multiple users of the file. This can
1066 * happen if a filedesc structure is shared by multiple
1067 * processes.
1068 */
1069 if (fp->f_iflags & FIF_WANTCLOSE) {
1070 /*
1071 * Another user of the file is already closing, and is
1072 * simply waiting for other users of the file to drain.
1073 * Release our usecount, and wake up the closer if it
1074 * is the only remaining use.
1075 */
1076 #ifdef DIAGNOSTIC
1077 if (fp->f_count != 0)
1078 panic("closef: wantclose and count != 0");
1079 if (fp->f_usecount < 2)
1080 panic("closef: wantclose and usecount < 2");
1081 #endif
1082 if (--fp->f_usecount == 1)
1083 wakeup(&fp->f_usecount);
1084 return (0);
1085 } else {
1086 /*
1087 * Decrement the reference count. If we were not the
1088 * last reference, then release our use and just
1089 * return.
1090 */
1091 if (--fp->f_count > 0) {
1092 #ifdef DIAGNOSTIC
1093 if (fp->f_usecount < 1)
1094 panic("closef: no wantclose and usecount < 1");
1095 #endif
1096 fp->f_usecount--;
1097 return (0);
1098 }
1099 if (fp->f_count < 0)
1100 panic("closef: count < 0");
1101 }
1102
1103 /*
1104 * The reference count is now 0. However, there may be
1105 * multiple potential users of this file. This can happen
1106 * if multiple processes shared a single filedesc structure.
1107 *
1108 * Notify these potential users that the file is closing.
1109 * This will prevent them from adding additional uses to
1110 * the file.
1111 */
1112 fp->f_iflags |= FIF_WANTCLOSE;
1113
1114 /*
1115 * We expect the caller to add a use to the file. So, if we
1116 * are the last user, usecount will be 1. If it is not, we
1117 * must wait for the usecount to drain. When it drains back
1118 * to 1, we will be awakened so that we may proceed with the
1119 * close.
1120 */
1121 #ifdef DIAGNOSTIC
1122 if (fp->f_usecount < 1)
1123 panic("closef: usecount < 1");
1124 #endif
1125 while (fp->f_usecount > 1)
1126 (void) tsleep(&fp->f_usecount, PRIBIO, "closef", 0);
1127 #ifdef DIAGNOSTIC
1128 if (fp->f_usecount != 1)
1129 panic("closef: usecount != 1");
1130 #endif
1131
1132 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1133 lf.l_whence = SEEK_SET;
1134 lf.l_start = 0;
1135 lf.l_len = 0;
1136 lf.l_type = F_UNLCK;
1137 vp = (struct vnode *)fp->f_data;
1138 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1139 }
1140 if (fp->f_ops)
1141 error = (*fp->f_ops->fo_close)(fp, p);
1142 else
1143 error = 0;
1144
1145 /* Nothing references the file now, drop the final use (us). */
1146 fp->f_usecount--;
1147
1148 ffree(fp);
1149 return (error);
1150 }
1151
1152 /*
1153 * Apply an advisory lock on a file descriptor.
1154 *
1155 * Just attempt to get a record lock of the requested type on
1156 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1157 */
1158 /* ARGSUSED */
1159 int
1160 sys_flock(struct proc *p, void *v, register_t *retval)
1161 {
1162 struct sys_flock_args /* {
1163 syscallarg(int) fd;
1164 syscallarg(int) how;
1165 } */ *uap = v;
1166 int fd, how, error;
1167 struct filedesc *fdp;
1168 struct file *fp;
1169 struct vnode *vp;
1170 struct flock lf;
1171
1172 fd = SCARG(uap, fd);
1173 how = SCARG(uap, how);
1174 fdp = p->p_fd;
1175 error = 0;
1176
1177 if ((fp = fd_getfile(fdp, fd)) == NULL)
1178 return (EBADF);
1179
1180 FILE_USE(fp);
1181
1182 if (fp->f_type != DTYPE_VNODE) {
1183 error = EOPNOTSUPP;
1184 goto out;
1185 }
1186
1187 vp = (struct vnode *)fp->f_data;
1188 lf.l_whence = SEEK_SET;
1189 lf.l_start = 0;
1190 lf.l_len = 0;
1191 if (how & LOCK_UN) {
1192 lf.l_type = F_UNLCK;
1193 fp->f_flag &= ~FHASLOCK;
1194 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1195 goto out;
1196 }
1197 if (how & LOCK_EX)
1198 lf.l_type = F_WRLCK;
1199 else if (how & LOCK_SH)
1200 lf.l_type = F_RDLCK;
1201 else {
1202 error = EINVAL;
1203 goto out;
1204 }
1205 fp->f_flag |= FHASLOCK;
1206 if (how & LOCK_NB)
1207 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK);
1208 else
1209 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
1210 F_FLOCK|F_WAIT);
1211 out:
1212 FILE_UNUSE(fp, p);
1213 return (error);
1214 }
1215
1216 /*
1217 * File Descriptor pseudo-device driver (/dev/fd/).
1218 *
1219 * Opening minor device N dup()s the file (if any) connected to file
1220 * descriptor N belonging to the calling process. Note that this driver
1221 * consists of only the ``open()'' routine, because all subsequent
1222 * references to this file will be direct to the other driver.
1223 */
1224 /* ARGSUSED */
1225 int
1226 filedescopen(dev_t dev, int mode, int type, struct proc *p)
1227 {
1228
1229 /*
1230 * XXX Kludge: set p->p_dupfd to contain the value of the
1231 * the file descriptor being sought for duplication. The error
1232 * return ensures that the vnode for this device will be released
1233 * by vn_open. Open will detect this special error and take the
1234 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1235 * will simply report the error.
1236 */
1237 p->p_dupfd = minor(dev);
1238 return (ENODEV);
1239 }
1240
1241 /*
1242 * Duplicate the specified descriptor to a free descriptor.
1243 */
1244 int
1245 dupfdopen(struct proc *p, int indx, int dfd, int mode, int error)
1246 {
1247 struct filedesc *fdp;
1248 struct file *wfp, *fp;
1249
1250 fdp = p->p_fd;
1251 /*
1252 * If the to-be-dup'd fd number is greater than the allowed number
1253 * of file descriptors, or the fd to be dup'd has already been
1254 * closed, reject. Note, check for new == old is necessary as
1255 * falloc could allocate an already closed to-be-dup'd descriptor
1256 * as the new descriptor.
1257 */
1258 fp = fdp->fd_ofiles[indx];
1259
1260 if ((wfp = fd_getfile(fdp, dfd)) == NULL)
1261 return (EBADF);
1262
1263 if (fp == wfp)
1264 return (EBADF);
1265
1266 FILE_USE(wfp);
1267
1268 /*
1269 * There are two cases of interest here.
1270 *
1271 * For ENODEV simply dup (dfd) to file descriptor
1272 * (indx) and return.
1273 *
1274 * For ENXIO steal away the file structure from (dfd) and
1275 * store it in (indx). (dfd) is effectively closed by
1276 * this operation.
1277 *
1278 * Any other error code is just returned.
1279 */
1280 switch (error) {
1281 case ENODEV:
1282 /*
1283 * Check that the mode the file is being opened for is a
1284 * subset of the mode of the existing descriptor.
1285 */
1286 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
1287 FILE_UNUSE(wfp, p);
1288 return (EACCES);
1289 }
1290 fdp->fd_ofiles[indx] = wfp;
1291 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1292 wfp->f_count++;
1293 fd_used(fdp, indx);
1294 FILE_UNUSE(wfp, p);
1295 return (0);
1296
1297 case ENXIO:
1298 /*
1299 * Steal away the file pointer from dfd, and stuff it into indx.
1300 */
1301 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
1302 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1303 fdp->fd_ofiles[dfd] = NULL;
1304 fdp->fd_ofileflags[dfd] = 0;
1305 /*
1306 * Complete the clean up of the filedesc structure by
1307 * recomputing the various hints.
1308 */
1309 fd_used(fdp, indx);
1310 fd_unused(fdp, dfd);
1311 FILE_UNUSE(wfp, p);
1312 return (0);
1313
1314 default:
1315 FILE_UNUSE(wfp, p);
1316 return (error);
1317 }
1318 /* NOTREACHED */
1319 }
1320
1321 /*
1322 * fcntl call which is being passed to the file's fs.
1323 */
1324 int
1325 fcntl_forfs(int fd, struct proc *p, int cmd, void *arg)
1326 {
1327 struct file *fp;
1328 struct filedesc *fdp;
1329 int error;
1330 u_int size;
1331 caddr_t data, memp;
1332 #define STK_PARAMS 128
1333 char stkbuf[STK_PARAMS];
1334
1335 /* fd's value was validated in sys_fcntl before calling this routine */
1336 fdp = p->p_fd;
1337 fp = fdp->fd_ofiles[fd];
1338
1339 if ((fp->f_flag & (FREAD | FWRITE)) == 0)
1340 return (EBADF);
1341
1342 /*
1343 * Interpret high order word to find amount of data to be
1344 * copied to/from the user's address space.
1345 */
1346 size = (size_t)F_PARAM_LEN(cmd);
1347 if (size > F_PARAM_MAX)
1348 return (EINVAL);
1349 memp = NULL;
1350 if (size > sizeof(stkbuf)) {
1351 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
1352 data = memp;
1353 } else
1354 data = stkbuf;
1355 if (cmd & F_FSIN) {
1356 if (size) {
1357 error = copyin(arg, data, size);
1358 if (error) {
1359 if (memp)
1360 free(memp, M_IOCTLOPS);
1361 return (error);
1362 }
1363 } else
1364 *(caddr_t *)data = arg;
1365 } else if ((cmd & F_FSOUT) && size)
1366 /*
1367 * Zero the buffer so the user always
1368 * gets back something deterministic.
1369 */
1370 memset(data, 0, size);
1371 else if (cmd & F_FSVOID)
1372 *(caddr_t *)data = arg;
1373
1374
1375 error = (*fp->f_ops->fo_fcntl)(fp, cmd, data, p);
1376
1377 /*
1378 * Copy any data to user, size was
1379 * already set and checked above.
1380 */
1381 if (error == 0 && (cmd & F_FSOUT) && size)
1382 error = copyout(data, arg, size);
1383 if (memp)
1384 free(memp, M_IOCTLOPS);
1385 return (error);
1386 }
1387
1388 /*
1389 * Close any files on exec?
1390 */
1391 void
1392 fdcloseexec(struct proc *p)
1393 {
1394 struct filedesc *fdp;
1395 int fd;
1396
1397 fdunshare(p);
1398 cwdunshare(p);
1399
1400 fdp = p->p_fd;
1401 for (fd = 0; fd <= fdp->fd_lastfile; fd++)
1402 if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
1403 (void) fdrelease(p, fd);
1404 }
1405
1406 /*
1407 * It is unsafe for set[ug]id processes to be started with file
1408 * descriptors 0..2 closed, as these descriptors are given implicit
1409 * significance in the Standard C library. fdcheckstd() will create a
1410 * descriptor referencing /dev/null for each of stdin, stdout, and
1411 * stderr that is not already open.
1412 */
1413 #define CHECK_UPTO 3
1414 int
1415 fdcheckstd(p)
1416 struct proc *p;
1417 {
1418 struct nameidata nd;
1419 struct filedesc *fdp;
1420 struct file *fp;
1421 struct file *devnullfp;
1422 struct proc *pp;
1423 register_t retval;
1424 int fd, i, error, flags = FREAD|FWRITE, devnull = -1;
1425 char closed[CHECK_UPTO * 3 + 1], which[3 + 1];
1426
1427 closed[0] = '\0';
1428 if ((fdp = p->p_fd) == NULL)
1429 return (0);
1430 for (i = 0; i < CHECK_UPTO; i++) {
1431 if (fdp->fd_ofiles[i] != NULL)
1432 continue;
1433 snprintf(which, sizeof(which), ",%d", i);
1434 strcat(closed, which);
1435 if (devnull < 0) {
1436 if ((error = falloc(p, &fp, &fd)) != 0)
1437 return (error);
1438 NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/null",
1439 p);
1440 if ((error = vn_open(&nd, flags, 0)) != 0) {
1441 FILE_UNUSE(fp, p);
1442 ffree(fp);
1443 fdremove(p->p_fd, fd);
1444 return (error);
1445 }
1446 fp->f_data = (caddr_t)nd.ni_vp;
1447 fp->f_flag = flags;
1448 fp->f_ops = &vnops;
1449 fp->f_type = DTYPE_VNODE;
1450 VOP_UNLOCK(nd.ni_vp, 0);
1451 devnull = fd;
1452 devnullfp = fp;
1453 FILE_SET_MATURE(fp);
1454 FILE_UNUSE(fp, p);
1455 } else {
1456 restart:
1457 if ((error = fdalloc(p, 0, &fd)) != 0) {
1458 if (error == ENOSPC) {
1459 fdexpand(p);
1460 goto restart;
1461 }
1462 return (error);
1463 }
1464
1465 FILE_USE(devnullfp);
1466 /* finishdup() will unuse the descriptors for us */
1467 if ((error = finishdup(p, devnull, fd, &retval)) != 0)
1468 return (error);
1469 }
1470 }
1471 if (closed[0] != '\0') {
1472 pp = p->p_pptr;
1473 log(LOG_WARNING, "set{u,g}id pid %d (%s) "
1474 "was invoked by uid %d ppid %d (%s) "
1475 "with fd %s closed\n",
1476 p->p_pid, p->p_comm, pp->p_ucred->cr_uid,
1477 pp->p_pid, pp->p_comm, &closed[1]);
1478 }
1479 return (0);
1480 }
1481 #undef CHECK_UPTO
1482