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