This source file includes following definitions.
- filedesc_init
- find_next_zero
- find_last_set
- fd_used
- fd_unused
- fd_getfile
- sys_dup
- sys_dup2
- sys_fcntl
- finishdup
- fdremove
- fdrelease
- sys_close
- sys_fstat
- sys_fpathconf
- fdalloc
- fdexpand
- falloc
- fdinit
- fdshare
- fdcopy
- fdfree
- closef
- sys_flock
- filedescopen
- dupfdopen
- fdcloseexec
- sys_closefrom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/filedesc.h>
43 #include <sys/kernel.h>
44 #include <sys/vnode.h>
45 #include <sys/proc.h>
46 #include <sys/file.h>
47 #include <sys/socket.h>
48 #include <sys/socketvar.h>
49 #include <sys/stat.h>
50 #include <sys/ioctl.h>
51 #include <sys/fcntl.h>
52 #include <sys/malloc.h>
53 #include <sys/syslog.h>
54 #include <sys/ucred.h>
55 #include <sys/unistd.h>
56 #include <sys/resourcevar.h>
57 #include <sys/conf.h>
58 #include <sys/mount.h>
59 #include <sys/syscallargs.h>
60 #include <sys/event.h>
61 #include <sys/pool.h>
62
63 #include <uvm/uvm_extern.h>
64
65 #include <sys/pipe.h>
66
67
68
69
70 struct filelist filehead;
71 int nfiles;
72
73 static __inline void fd_used(struct filedesc *, int);
74 static __inline void fd_unused(struct filedesc *, int);
75 static __inline int find_next_zero(u_int *, int, u_int);
76 int finishdup(struct proc *, struct file *, int, int, register_t *);
77 int find_last_set(struct filedesc *, int);
78
79 struct pool file_pool;
80 struct pool fdesc_pool;
81
82 void
83 filedesc_init(void)
84 {
85 pool_init(&file_pool, sizeof(struct file), 0, 0, 0, "filepl",
86 &pool_allocator_nointr);
87 pool_init(&fdesc_pool, sizeof(struct filedesc0), 0, 0, 0, "fdescpl",
88 &pool_allocator_nointr);
89 LIST_INIT(&filehead);
90 }
91
92 static __inline int
93 find_next_zero (u_int *bitmap, int want, u_int bits)
94 {
95 int i, off, maxoff;
96 u_int sub;
97
98 if (want > bits)
99 return -1;
100
101 off = want >> NDENTRYSHIFT;
102 i = want & NDENTRYMASK;
103 if (i) {
104 sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i));
105 if (sub != ~0)
106 goto found;
107 off++;
108 }
109
110 maxoff = NDLOSLOTS(bits);
111 while (off < maxoff) {
112 if ((sub = bitmap[off]) != ~0)
113 goto found;
114 off++;
115 }
116
117 return -1;
118
119 found:
120 return (off << NDENTRYSHIFT) + ffs(~sub) - 1;
121 }
122
123 int
124 find_last_set(struct filedesc *fd, int last)
125 {
126 int off, i;
127 struct file **ofiles = fd->fd_ofiles;
128 u_int *bitmap = fd->fd_lomap;
129
130 off = (last - 1) >> NDENTRYSHIFT;
131
132 while (off >= 0 && !bitmap[off])
133 off--;
134 if (off < 0)
135 return 0;
136
137 i = ((off + 1) << NDENTRYSHIFT) - 1;
138 if (i >= last)
139 i = last - 1;
140
141 while (i > 0 && ofiles[i] == NULL)
142 i--;
143 return i;
144 }
145
146 static __inline void
147 fd_used(struct filedesc *fdp, int fd)
148 {
149 u_int off = fd >> NDENTRYSHIFT;
150
151 fdp->fd_lomap[off] |= 1 << (fd & NDENTRYMASK);
152 if (fdp->fd_lomap[off] == ~0)
153 fdp->fd_himap[off >> NDENTRYSHIFT] |= 1 << (off & NDENTRYMASK);
154
155 if (fd > fdp->fd_lastfile)
156 fdp->fd_lastfile = fd;
157 }
158
159 static __inline void
160 fd_unused(struct filedesc *fdp, int fd)
161 {
162 u_int off = fd >> NDENTRYSHIFT;
163
164 if (fd < fdp->fd_freefile)
165 fdp->fd_freefile = fd;
166
167 if (fdp->fd_lomap[off] == ~0)
168 fdp->fd_himap[off >> NDENTRYSHIFT] &= ~(1 << (off & NDENTRYMASK));
169 fdp->fd_lomap[off] &= ~(1 << (fd & NDENTRYMASK));
170
171 #ifdef DIAGNOSTIC
172 if (fd > fdp->fd_lastfile)
173 panic("fd_unused: fd_lastfile inconsistent");
174 #endif
175 if (fd == fdp->fd_lastfile)
176 fdp->fd_lastfile = find_last_set(fdp, fd);
177 }
178
179 struct file *
180 fd_getfile(struct filedesc *fdp, int fd)
181 {
182 struct file *fp;
183
184 if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
185 return (NULL);
186
187 if (!FILE_IS_USABLE(fp))
188 return (NULL);
189
190 return (fp);
191 }
192
193
194
195
196
197
198
199
200
201 int
202 sys_dup(struct proc *p, void *v, register_t *retval)
203 {
204 struct sys_dup_args
205
206 *uap = v;
207 struct filedesc *fdp = p->p_fd;
208 int old = SCARG(uap, fd);
209 struct file *fp;
210 int new;
211 int error;
212
213 restart:
214 if ((fp = fd_getfile(fdp, old)) == NULL)
215 return (EBADF);
216 FREF(fp);
217 fdplock(fdp);
218 if ((error = fdalloc(p, 0, &new)) != 0) {
219 FRELE(fp);
220 if (error == ENOSPC) {
221 fdexpand(p);
222 fdpunlock(fdp);
223 goto restart;
224 }
225 goto out;
226 }
227 error = finishdup(p, fp, old, new, retval);
228
229 out:
230 fdpunlock(fdp);
231 return (error);
232 }
233
234
235
236
237
238 int
239 sys_dup2(struct proc *p, void *v, register_t *retval)
240 {
241 struct sys_dup2_args
242
243
244 *uap = v;
245 int old = SCARG(uap, from), new = SCARG(uap, to);
246 struct filedesc *fdp = p->p_fd;
247 struct file *fp;
248 int i, error;
249
250 restart:
251 if ((fp = fd_getfile(fdp, old)) == NULL)
252 return (EBADF);
253 if ((u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
254 (u_int)new >= maxfiles)
255 return (EBADF);
256 if (old == new) {
257
258
259
260
261
262 *retval = new;
263 return (0);
264 }
265 FREF(fp);
266 fdplock(fdp);
267 if (new >= fdp->fd_nfiles) {
268 if ((error = fdalloc(p, new, &i)) != 0) {
269 FRELE(fp);
270 if (error == ENOSPC) {
271 fdexpand(p);
272 fdpunlock(fdp);
273 goto restart;
274 }
275 goto out;
276 }
277 if (new != i)
278 panic("dup2: fdalloc");
279 }
280
281 error = finishdup(p, fp, old, new, retval);
282
283 out:
284 fdpunlock(fdp);
285 return (error);
286 }
287
288
289
290
291
292 int
293 sys_fcntl(struct proc *p, void *v, register_t *retval)
294 {
295 struct sys_fcntl_args
296
297
298
299 *uap = v;
300 int fd = SCARG(uap, fd);
301 struct filedesc *fdp = p->p_fd;
302 struct file *fp;
303 struct vnode *vp;
304 int i, tmp, newmin, flg = F_POSIX;
305 struct flock fl;
306 int error = 0;
307
308 restart:
309 if ((fp = fd_getfile(fdp, fd)) == NULL)
310 return (EBADF);
311 FREF(fp);
312 switch (SCARG(uap, cmd)) {
313
314 case F_DUPFD:
315 newmin = (long)SCARG(uap, arg);
316 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
317 (u_int)newmin >= maxfiles) {
318 error = EINVAL;
319 break;
320 }
321 fdplock(fdp);
322 if ((error = fdalloc(p, newmin, &i)) != 0) {
323 if (error == ENOSPC) {
324 fdexpand(p);
325 FRELE(fp);
326 fdpunlock(fdp);
327 goto restart;
328 }
329 }
330
331 if (!error)
332 error = finishdup(p, fp, fd, i, retval);
333 else
334 FRELE(fp);
335
336 fdpunlock(fdp);
337 return (error);
338
339 case F_GETFD:
340 *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
341 break;
342
343 case F_SETFD:
344 if ((long)SCARG(uap, arg) & 1)
345 fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
346 else
347 fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
348 break;
349
350 case F_GETFL:
351 *retval = OFLAGS(fp->f_flag);
352 break;
353
354 case F_SETFL:
355 fp->f_flag &= ~FCNTLFLAGS;
356 fp->f_flag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
357 tmp = fp->f_flag & FNONBLOCK;
358 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
359 if (error)
360 break;
361 tmp = fp->f_flag & FASYNC;
362 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
363 if (!error)
364 break;
365 fp->f_flag &= ~FNONBLOCK;
366 tmp = 0;
367 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
368 break;
369
370 case F_GETOWN:
371 if (fp->f_type == DTYPE_SOCKET) {
372 *retval = ((struct socket *)fp->f_data)->so_pgid;
373 break;
374 }
375 error = (*fp->f_ops->fo_ioctl)
376 (fp, TIOCGPGRP, (caddr_t)&tmp, p);
377 *retval = -tmp;
378 break;
379
380 case F_SETOWN:
381 if (fp->f_type == DTYPE_SOCKET) {
382 struct socket *so = (struct socket *)fp->f_data;
383
384 so->so_pgid = (long)SCARG(uap, arg);
385 so->so_siguid = p->p_cred->p_ruid;
386 so->so_sigeuid = p->p_ucred->cr_uid;
387 break;
388 }
389 if ((long)SCARG(uap, arg) <= 0) {
390 SCARG(uap, arg) = (void *)(-(long)SCARG(uap, arg));
391 } else {
392 struct proc *p1 = pfind((long)SCARG(uap, arg));
393 if (p1 == 0) {
394 error = ESRCH;
395 break;
396 }
397 SCARG(uap, arg) = (void *)(long)p1->p_pgrp->pg_id;
398 }
399 error = ((*fp->f_ops->fo_ioctl)
400 (fp, TIOCSPGRP, (caddr_t)&SCARG(uap, arg), p));
401 break;
402
403 case F_SETLKW:
404 flg |= F_WAIT;
405
406
407 case F_SETLK:
408 if (fp->f_type != DTYPE_VNODE) {
409 error = EBADF;
410 break;
411 }
412 vp = (struct vnode *)fp->f_data;
413
414 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
415 sizeof (fl));
416 if (error)
417 break;
418 if (fl.l_whence == SEEK_CUR) {
419 if (fl.l_start == 0 && fl.l_len < 0) {
420
421 fl.l_len = -fl.l_len;
422 fl.l_start = fp->f_offset - fl.l_len;
423 } else
424 fl.l_start += fp->f_offset;
425 }
426 switch (fl.l_type) {
427
428 case F_RDLCK:
429 if ((fp->f_flag & FREAD) == 0) {
430 error = EBADF;
431 goto out;
432 }
433 atomic_setbits_int(&p->p_flag, P_ADVLOCK);
434 error = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
435 goto out;
436
437 case F_WRLCK:
438 if ((fp->f_flag & FWRITE) == 0) {
439 error = EBADF;
440 goto out;
441 }
442 atomic_setbits_int(&p->p_flag, P_ADVLOCK);
443 error = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
444 goto out;
445
446 case F_UNLCK:
447 error = (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
448 F_POSIX));
449 goto out;
450
451 default:
452 error = EINVAL;
453 goto out;
454 }
455
456 case F_GETLK:
457 if (fp->f_type != DTYPE_VNODE) {
458 error = EBADF;
459 break;
460 }
461 vp = (struct vnode *)fp->f_data;
462
463 error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
464 sizeof (fl));
465 if (error)
466 break;
467 if (fl.l_whence == SEEK_CUR) {
468 if (fl.l_start == 0 && fl.l_len < 0) {
469
470 fl.l_len = -fl.l_len;
471 fl.l_start = fp->f_offset - fl.l_len;
472 } else
473 fl.l_start += fp->f_offset;
474 }
475 if (fl.l_type != F_RDLCK &&
476 fl.l_type != F_WRLCK &&
477 fl.l_type != F_UNLCK &&
478 fl.l_type != 0) {
479 error = EINVAL;
480 break;
481 }
482 error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX);
483 if (error)
484 break;
485 error = (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg),
486 sizeof (fl)));
487 break;
488
489 default:
490 error = EINVAL;
491 break;
492 }
493 out:
494 FRELE(fp);
495 return (error);
496 }
497
498
499
500
501 int
502 finishdup(struct proc *p, struct file *fp, int old, int new, register_t *retval)
503 {
504 struct file *oldfp;
505 struct filedesc *fdp = p->p_fd;
506
507 if (fp->f_count == LONG_MAX-2) {
508 FRELE(fp);
509 return (EDEADLK);
510 }
511
512
513
514
515
516 oldfp = fdp->fd_ofiles[new];
517 if (oldfp != NULL)
518 FREF(oldfp);
519
520 fdp->fd_ofiles[new] = fp;
521 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
522 fp->f_count++;
523 FRELE(fp);
524 if (oldfp == NULL)
525 fd_used(fdp, new);
526 *retval = new;
527
528 if (oldfp != NULL) {
529 if (new < fdp->fd_knlistsize)
530 knote_fdclose(p, new);
531 closef(oldfp, p);
532 }
533
534 return (0);
535 }
536
537 void
538 fdremove(struct filedesc *fdp, int fd)
539 {
540 fdp->fd_ofiles[fd] = NULL;
541 fd_unused(fdp, fd);
542 }
543
544 int
545 fdrelease(struct proc *p, int fd)
546 {
547 struct filedesc *fdp = p->p_fd;
548 struct file **fpp, *fp;
549
550
551
552
553
554 fpp = &fdp->fd_ofiles[fd];
555 fp = *fpp;
556 if (fp == NULL)
557 return (EBADF);
558 FREF(fp);
559 *fpp = NULL;
560 fdp->fd_ofileflags[fd] = 0;
561 fd_unused(fdp, fd);
562 if (fd < fdp->fd_knlistsize)
563 knote_fdclose(p, fd);
564 return (closef(fp, p));
565 }
566
567
568
569
570
571 int
572 sys_close(struct proc *p, void *v, register_t *retval)
573 {
574 struct sys_close_args
575
576 *uap = v;
577 int fd = SCARG(uap, fd), error;
578 struct filedesc *fdp = p->p_fd;
579
580 if (fd_getfile(fdp, fd) == NULL)
581 return (EBADF);
582 fdplock(fdp);
583 error = fdrelease(p, fd);
584 fdpunlock(fdp);
585
586 return (error);
587 }
588
589
590
591
592
593 int
594 sys_fstat(struct proc *p, void *v, register_t *retval)
595 {
596 struct sys_fstat_args
597
598
599 *uap = v;
600 int fd = SCARG(uap, fd);
601 struct filedesc *fdp = p->p_fd;
602 struct file *fp;
603 struct stat ub;
604 int error;
605
606 if ((fp = fd_getfile(fdp, fd)) == NULL)
607 return (EBADF);
608 FREF(fp);
609 error = (*fp->f_ops->fo_stat)(fp, &ub, p);
610 FRELE(fp);
611 if (error == 0) {
612
613
614
615
616 if (suser(p, 0))
617 ub.st_gen = 0;
618 error = copyout((caddr_t)&ub, (caddr_t)SCARG(uap, sb),
619 sizeof (ub));
620 }
621 return (error);
622 }
623
624
625
626
627
628 int
629 sys_fpathconf(struct proc *p, void *v, register_t *retval)
630 {
631 struct sys_fpathconf_args
632
633
634 *uap = v;
635 int fd = SCARG(uap, fd);
636 struct filedesc *fdp = p->p_fd;
637 struct file *fp;
638 struct vnode *vp;
639 int error;
640
641 if ((fp = fd_getfile(fdp, fd)) == NULL)
642 return (EBADF);
643 FREF(fp);
644 switch (fp->f_type) {
645 case DTYPE_PIPE:
646 case DTYPE_SOCKET:
647 if (SCARG(uap, name) != _PC_PIPE_BUF) {
648 error = EINVAL;
649 break;
650 }
651 *retval = PIPE_BUF;
652 error = 0;
653 break;
654
655 case DTYPE_VNODE:
656 vp = (struct vnode *)fp->f_data;
657 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
658 error = VOP_PATHCONF(vp, SCARG(uap, name), retval);
659 VOP_UNLOCK(vp, 0, p);
660 break;
661
662 default:
663 error = EOPNOTSUPP;
664 break;
665 }
666 FRELE(fp);
667 return (error);
668 }
669
670
671
672
673 int
674 fdalloc(struct proc *p, int want, int *result)
675 {
676 struct filedesc *fdp = p->p_fd;
677 int lim, last, i;
678 u_int new, off;
679
680
681
682
683
684
685 restart:
686 lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
687 last = min(fdp->fd_nfiles, lim);
688 if ((i = want) < fdp->fd_freefile)
689 i = fdp->fd_freefile;
690 off = i >> NDENTRYSHIFT;
691 new = find_next_zero(fdp->fd_himap, off,
692 (last + NDENTRIES - 1) >> NDENTRYSHIFT);
693 if (new != -1) {
694 i = find_next_zero(&fdp->fd_lomap[new],
695 new > off ? 0 : i & NDENTRYMASK,
696 NDENTRIES);
697 if (i == -1) {
698
699
700
701
702 want = (new + 1) << NDENTRYSHIFT;
703 goto restart;
704 }
705 i += (new << NDENTRYSHIFT);
706 if (i < last) {
707 fd_used(fdp, i);
708 if (want <= fdp->fd_freefile)
709 fdp->fd_freefile = i;
710 *result = i;
711 return (0);
712 }
713 }
714 if (fdp->fd_nfiles >= lim)
715 return (EMFILE);
716
717 return (ENOSPC);
718 }
719
720 void
721 fdexpand(struct proc *p)
722 {
723 struct filedesc *fdp = p->p_fd;
724 int nfiles, i;
725 struct file **newofile;
726 char *newofileflags;
727 u_int *newhimap, *newlomap;
728
729
730
731
732 if (fdp->fd_nfiles < NDEXTENT)
733 nfiles = NDEXTENT;
734 else
735 nfiles = 2 * fdp->fd_nfiles;
736
737 newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK);
738 newofileflags = (char *) &newofile[nfiles];
739
740
741
742
743
744 bcopy(fdp->fd_ofiles, newofile,
745 (i = sizeof(struct file *) * fdp->fd_nfiles));
746 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
747 bcopy(fdp->fd_ofileflags, newofileflags,
748 (i = sizeof(char) * fdp->fd_nfiles));
749 bzero(newofileflags + i, nfiles * sizeof(char) - i);
750
751 if (fdp->fd_nfiles > NDFILE)
752 free(fdp->fd_ofiles, M_FILEDESC);
753
754 if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) {
755 newhimap = malloc(NDHISLOTS(nfiles) * sizeof(u_int),
756 M_FILEDESC, M_WAITOK);
757 newlomap = malloc(NDLOSLOTS(nfiles) * sizeof(u_int),
758 M_FILEDESC, M_WAITOK);
759
760 bcopy(fdp->fd_himap, newhimap,
761 (i = NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int)));
762 bzero((char *)newhimap + i,
763 NDHISLOTS(nfiles) * sizeof(u_int) - i);
764
765 bcopy(fdp->fd_lomap, newlomap,
766 (i = NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int)));
767 bzero((char *)newlomap + i,
768 NDLOSLOTS(nfiles) * sizeof(u_int) - i);
769
770 if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
771 free(fdp->fd_himap, M_FILEDESC);
772 free(fdp->fd_lomap, M_FILEDESC);
773 }
774 fdp->fd_himap = newhimap;
775 fdp->fd_lomap = newlomap;
776 }
777 fdp->fd_ofiles = newofile;
778 fdp->fd_ofileflags = newofileflags;
779 fdp->fd_nfiles = nfiles;
780 }
781
782
783
784
785
786 int
787 falloc(struct proc *p, struct file **resultfp, int *resultfd)
788 {
789 struct file *fp, *fq;
790 int error, i;
791
792 restart:
793 if ((error = fdalloc(p, 0, &i)) != 0) {
794 if (error == ENOSPC) {
795 fdexpand(p);
796 goto restart;
797 }
798 return (error);
799 }
800 if (nfiles >= maxfiles) {
801 fd_unused(p->p_fd, i);
802 tablefull("file");
803 return (ENFILE);
804 }
805
806
807
808
809
810
811 nfiles++;
812 fp = pool_get(&file_pool, PR_WAITOK);
813 bzero(fp, sizeof(struct file));
814 fp->f_iflags = FIF_LARVAL;
815 if ((fq = p->p_fd->fd_ofiles[0]) != NULL) {
816 LIST_INSERT_AFTER(fq, fp, f_list);
817 } else {
818 LIST_INSERT_HEAD(&filehead, fp, f_list);
819 }
820 p->p_fd->fd_ofiles[i] = fp;
821 fp->f_count = 1;
822 fp->f_cred = p->p_ucred;
823 crhold(fp->f_cred);
824 if (resultfp)
825 *resultfp = fp;
826 if (resultfd)
827 *resultfd = i;
828 FREF(fp);
829 return (0);
830 }
831
832
833
834
835 struct filedesc *
836 fdinit(struct proc *p)
837 {
838 struct filedesc0 *newfdp;
839 extern int cmask;
840
841 newfdp = pool_get(&fdesc_pool, PR_WAITOK);
842 bzero(newfdp, sizeof(struct filedesc0));
843 if (p != NULL) {
844 struct filedesc *fdp = p->p_fd;
845
846 newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
847 VREF(newfdp->fd_fd.fd_cdir);
848 newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
849 if (newfdp->fd_fd.fd_rdir)
850 VREF(newfdp->fd_fd.fd_rdir);
851 }
852 rw_init(&newfdp->fd_fd.fd_lock, "fdlock");
853
854
855 newfdp->fd_fd.fd_refcnt = 1;
856 newfdp->fd_fd.fd_cmask = cmask;
857 newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
858 newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
859 newfdp->fd_fd.fd_nfiles = NDFILE;
860 newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
861 newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
862 newfdp->fd_fd.fd_knlistsize = -1;
863
864 newfdp->fd_fd.fd_freefile = 0;
865 newfdp->fd_fd.fd_lastfile = 0;
866
867 return (&newfdp->fd_fd);
868 }
869
870
871
872
873 struct filedesc *
874 fdshare(struct proc *p)
875 {
876 p->p_fd->fd_refcnt++;
877 return (p->p_fd);
878 }
879
880
881
882
883 struct filedesc *
884 fdcopy(struct proc *p)
885 {
886 struct filedesc *newfdp, *fdp = p->p_fd;
887 struct file **fpp;
888 int i;
889
890 newfdp = pool_get(&fdesc_pool, PR_WAITOK);
891 bcopy(fdp, newfdp, sizeof(struct filedesc));
892 if (newfdp->fd_cdir)
893 VREF(newfdp->fd_cdir);
894 if (newfdp->fd_rdir)
895 VREF(newfdp->fd_rdir);
896 newfdp->fd_refcnt = 1;
897
898
899
900
901
902
903
904 if (newfdp->fd_lastfile < NDFILE) {
905 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
906 newfdp->fd_ofileflags =
907 ((struct filedesc0 *) newfdp)->fd_dfileflags;
908 i = NDFILE;
909 } else {
910
911
912
913
914
915 i = newfdp->fd_nfiles;
916 while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
917 i /= 2;
918 newfdp->fd_ofiles = malloc(i * OFILESIZE, M_FILEDESC, M_WAITOK);
919 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
920 }
921 if (NDHISLOTS(i) <= NDHISLOTS(NDFILE)) {
922 newfdp->fd_himap =
923 ((struct filedesc0 *) newfdp)->fd_dhimap;
924 newfdp->fd_lomap =
925 ((struct filedesc0 *) newfdp)->fd_dlomap;
926 } else {
927 newfdp->fd_himap = malloc(NDHISLOTS(i) * sizeof(u_int),
928 M_FILEDESC, M_WAITOK);
929 newfdp->fd_lomap = malloc(NDLOSLOTS(i) * sizeof(u_int),
930 M_FILEDESC, M_WAITOK);
931 }
932 newfdp->fd_nfiles = i;
933 bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
934 bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
935 bcopy(fdp->fd_himap, newfdp->fd_himap, NDHISLOTS(i) * sizeof(u_int));
936 bcopy(fdp->fd_lomap, newfdp->fd_lomap, NDLOSLOTS(i) * sizeof(u_int));
937
938
939
940
941 if (newfdp->fd_knlistsize != -1) {
942 fpp = newfdp->fd_ofiles;
943 for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++)
944 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE)
945 fdremove(newfdp, i);
946 newfdp->fd_knlist = NULL;
947 newfdp->fd_knlistsize = -1;
948 newfdp->fd_knhash = NULL;
949 newfdp->fd_knhashmask = 0;
950 }
951
952 fpp = newfdp->fd_ofiles;
953 for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++)
954 if (*fpp != NULL) {
955
956
957
958
959
960 if ((*fpp)->f_count == LONG_MAX-2)
961 fdremove(newfdp, i);
962 else
963 (*fpp)->f_count++;
964 }
965 return (newfdp);
966 }
967
968
969
970
971 void
972 fdfree(struct proc *p)
973 {
974 struct filedesc *fdp = p->p_fd;
975 struct file **fpp, *fp;
976 int i;
977
978 if (--fdp->fd_refcnt > 0)
979 return;
980 fpp = fdp->fd_ofiles;
981 for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
982 fp = *fpp;
983 if (fp != NULL) {
984 FREF(fp);
985 *fpp = NULL;
986 (void) closef(fp, p);
987 }
988 }
989 p->p_fd = NULL;
990 if (fdp->fd_nfiles > NDFILE)
991 free(fdp->fd_ofiles, M_FILEDESC);
992 if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
993 free(fdp->fd_himap, M_FILEDESC);
994 free(fdp->fd_lomap, M_FILEDESC);
995 }
996 if (fdp->fd_cdir)
997 vrele(fdp->fd_cdir);
998 if (fdp->fd_rdir)
999 vrele(fdp->fd_rdir);
1000 if (fdp->fd_knlist)
1001 FREE(fdp->fd_knlist, M_TEMP);
1002 if (fdp->fd_knhash)
1003 FREE(fdp->fd_knhash, M_TEMP);
1004 pool_put(&fdesc_pool, fdp);
1005 }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015 int
1016 closef(struct file *fp, struct proc *p)
1017 {
1018 struct vnode *vp;
1019 struct flock lf;
1020 int error;
1021
1022 if (fp == NULL)
1023 return (0);
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033 if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
1034 lf.l_whence = SEEK_SET;
1035 lf.l_start = 0;
1036 lf.l_len = 0;
1037 lf.l_type = F_UNLCK;
1038 vp = (struct vnode *)fp->f_data;
1039 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
1040 }
1041
1042
1043
1044
1045
1046
1047
1048 if ((fp->f_iflags & FIF_WANTCLOSE) != 0) {
1049 FRELE(fp);
1050 return (0);
1051 }
1052
1053 if (--fp->f_count > 0) {
1054 FRELE(fp);
1055 return (0);
1056 }
1057
1058 #ifdef DIAGNOSTIC
1059 if (fp->f_count < 0)
1060 panic("closef: count < 0");
1061 #endif
1062
1063
1064 fp->f_iflags |= FIF_WANTCLOSE;
1065 while (fp->f_usecount > 1)
1066 tsleep(&fp->f_usecount, PRIBIO, "closef", 0);
1067
1068 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1069 lf.l_whence = SEEK_SET;
1070 lf.l_start = 0;
1071 lf.l_len = 0;
1072 lf.l_type = F_UNLCK;
1073 vp = (struct vnode *)fp->f_data;
1074 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1075 }
1076 if (fp->f_ops)
1077 error = (*fp->f_ops->fo_close)(fp, p);
1078 else
1079 error = 0;
1080
1081
1082 LIST_REMOVE(fp, f_list);
1083 crfree(fp->f_cred);
1084 #ifdef DIAGNOSTIC
1085 if (fp->f_count != 0 || fp->f_usecount != 1)
1086 panic("closef: count: %d/%d", fp->f_count, fp->f_usecount);
1087 #endif
1088 nfiles--;
1089 pool_put(&file_pool, fp);
1090
1091 return (error);
1092 }
1093
1094
1095
1096
1097
1098
1099
1100
1101 int
1102 sys_flock(struct proc *p, void *v, register_t *retval)
1103 {
1104 struct sys_flock_args
1105
1106
1107 *uap = v;
1108 int fd = SCARG(uap, fd);
1109 int how = SCARG(uap, how);
1110 struct filedesc *fdp = p->p_fd;
1111 struct file *fp;
1112 struct vnode *vp;
1113 struct flock lf;
1114 int error;
1115
1116 if ((fp = fd_getfile(fdp, fd)) == NULL)
1117 return (EBADF);
1118 if (fp->f_type != DTYPE_VNODE)
1119 return (EOPNOTSUPP);
1120 vp = (struct vnode *)fp->f_data;
1121 lf.l_whence = SEEK_SET;
1122 lf.l_start = 0;
1123 lf.l_len = 0;
1124 if (how & LOCK_UN) {
1125 lf.l_type = F_UNLCK;
1126 fp->f_flag &= ~FHASLOCK;
1127 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1128 goto out;
1129 }
1130 if (how & LOCK_EX)
1131 lf.l_type = F_WRLCK;
1132 else if (how & LOCK_SH)
1133 lf.l_type = F_RDLCK;
1134 else {
1135 error = EINVAL;
1136 goto out;
1137 }
1138 fp->f_flag |= FHASLOCK;
1139 if (how & LOCK_NB)
1140 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK);
1141 else
1142 error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT);
1143 out:
1144 return (error);
1145 }
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156 int
1157 filedescopen(dev_t dev, int mode, int type, struct proc *p)
1158 {
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168 p->p_dupfd = minor(dev);
1169 return (ENODEV);
1170 }
1171
1172
1173
1174
1175 int
1176 dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode, int error)
1177 {
1178 struct file *wfp;
1179
1180
1181
1182
1183
1184 if ((curproc->p_flag & (P_SUGIDEXEC | P_SUGID))) {
1185 if (curproc->p_descfd == 255)
1186 return (EPERM);
1187 if (curproc->p_descfd != curproc->p_dupfd)
1188 return (EPERM);
1189 }
1190
1191
1192
1193
1194
1195
1196
1197
1198 if ((wfp = fd_getfile(fdp, dfd)) == NULL)
1199 return (EBADF);
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213 switch (error) {
1214 case ENODEV:
1215
1216
1217
1218
1219 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
1220 return (EACCES);
1221 if (wfp->f_count == LONG_MAX-2)
1222 return (EDEADLK);
1223 fdp->fd_ofiles[indx] = wfp;
1224 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1225 wfp->f_count++;
1226 fd_used(fdp, indx);
1227 return (0);
1228
1229 case ENXIO:
1230
1231
1232
1233 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
1234 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1235 fdp->fd_ofiles[dfd] = NULL;
1236 fdp->fd_ofileflags[dfd] = 0;
1237
1238
1239
1240
1241 fd_used(fdp, indx);
1242 fd_unused(fdp, dfd);
1243 return (0);
1244
1245 default:
1246 return (error);
1247 }
1248
1249 }
1250
1251
1252
1253
1254 void
1255 fdcloseexec(struct proc *p)
1256 {
1257 struct filedesc *fdp = p->p_fd;
1258 int fd;
1259
1260 for (fd = 0; fd <= fdp->fd_lastfile; fd++)
1261 if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
1262 (void) fdrelease(p, fd);
1263 }
1264
1265 int
1266 sys_closefrom(struct proc *p, void *v, register_t *retval)
1267 {
1268 struct sys_closefrom_args *uap = v;
1269 struct filedesc *fdp = p->p_fd;
1270 u_int startfd, i;
1271
1272 startfd = SCARG(uap, fd);
1273 fdplock(fdp);
1274
1275 if (startfd > fdp->fd_lastfile) {
1276 fdpunlock(fdp);
1277 return (EBADF);
1278 }
1279
1280 for (i = startfd; i <= fdp->fd_lastfile; i++)
1281 fdrelease(p, i);
1282
1283 fdpunlock(fdp);
1284 return (0);
1285 }