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