1 /*
2 * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * $Id: descrip.c,v 1.1 94/10/20 00:02:49 bill Exp Locker: bill $
34 *
35 * File instance and file descriptor management and system calls.
36 */
37
38 #include "sys/param.h"
39 #include "sys/stat.h"
40 #include "sys/ioctl.h"
41 #include "sys/fcntl.h"
42 #include "sys/syslog.h"
43 #include "sys/errno.h"
44 #include "filedesc.h"
45 #include "kernel.h" /* time */
46 #include "malloc.h"
47 #include "modconfig.h"
48 #include "proc.h"
49 /*#include "socketvar.h"*/
50 #include "resourcevar.h"
51 #include "uio.h"
52 #ifdef KTRACE
53 #include "sys/ktrace.h"
54 #endif
55
56
57 #include "vnode.h"
58
59 #include "prototypes.h"
60
61 /*
62 * Descriptor management.
63 */
64 struct file *filehead; /* head of list of open files */
65 int nfiles; /* actual number of open files */
66 static int fdopen(dev_t dev, int mode, int type, struct proc *p);
67 /*int fdalloc(struct proc *p, int want, int *result);*/
68 static int selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval);
69
70
71
72
73
74 /*
75 * Descriptor system calls, both BSD and POSIX.
76 */
77
78 /* BSD file descriptor "table" size (number of descriptors */
79 int
getdtablesize(p,uap,retval)80 getdtablesize(p, uap, retval)
81 struct proc *p;
82 void *uap;
83 int *retval;
84 {
85
86 *retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
87 return (0);
88 }
89
90
91
92 /* POSIX Duplicate a file descriptor. */
93 int
dup(p,uap,retval)94 dup(p, uap, retval)
95 struct proc *p;
96 struct args {
97 int i;
98 } *uap;
99 int *retval;
100 {
101 register struct filedesc *fdp = p->p_fd;
102 struct file *fp;
103 int fd, error;
104
105 if ((unsigned)uap->i >= fdp->fd_nfiles ||
106 (fp = fdp->fd_ofiles[uap->i]) == NULL)
107 return (EBADF);
108
109 if (error = fdalloc(p, 0, &fd))
110 return (error);
111
112 fdp->fd_ofiles[fd] = fp;
113 fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE;
114 fp->f_count++;
115 if (fd > fdp->fd_lastfile)
116 fdp->fd_lastfile = fd;
117 *retval = fd;
118 return (0);
119 }
120
121
122
123
124 /* POSIX Duplicate a file descriptor to a particular value. */
125 int
dup2(p,uap,retval)126 dup2(p, uap, retval)
127 struct proc *p;
128 struct args {
129 u_int from;
130 u_int to;
131 } *uap;
132 int *retval;
133 {
134 register struct filedesc *fdp = p->p_fd;
135 register struct file *fp;
136 register u_int old = uap->from, new = uap->to;
137 int i, error;
138
139 if (old >= fdp->fd_nfiles ||
140 (fp = fdp->fd_ofiles[old]) == NULL ||
141 new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
142 return (EBADF);
143
144 *retval = new;
145 if (old == new)
146 return (0);
147
148 if (new >= fdp->fd_nfiles) {
149 if (error = fdalloc(p, new, &i))
150 return (error);
151 #ifdef DIAGNOSTIC
152 if (new != i)
153 panic("dup2: fdalloc");
154 #endif
155 } else if (fdp->fd_ofiles[new]) {
156 if (fdp->fd_ofileflags[new] & UF_MAPPED)
157 (void) munmapfd(p, new);
158 /* dup2() must succeed even if the close has an error.*/
159 (void) closef(fdp->fd_ofiles[new], p);
160 }
161
162 fdp->fd_ofiles[new] = fp;
163 fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
164 fp->f_count++;
165 if (new > fdp->fd_lastfile)
166 fdp->fd_lastfile = new;
167 return (0);
168 }
169
170
171
172
173 /* POSIX file control system call. */
174 int
fcntl(p,uap,retval)175 fcntl(p, uap, retval)
176 struct proc *p;
177 struct args {
178 int fd;
179 int cmd;
180 int arg;
181 } *uap;
182 int *retval;
183 {
184 struct filedesc *fdp = p->p_fd;
185 struct file *fp;
186 char *pop;
187 struct vnode *vp;
188 int cmd, i, tmp, error, flg = F_POSIX;
189 struct flock fl;
190
191 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
192 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
193 return (EBADF);
194
195 pop = &fdp->fd_ofileflags[uap->fd];
196 switch(uap->cmd) {
197 case F_DUPFD:
198 if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
199 return (EINVAL);
200 if (error = fdalloc(p, uap->arg, &i))
201 return (error);
202 fdp->fd_ofiles[i] = fp;
203 fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE;
204 fp->f_count++;
205 if (i > fdp->fd_lastfile)
206 fdp->fd_lastfile = i;
207 *retval = i;
208 return (0);
209
210 case F_GETFD:
211 *retval = *pop & UF_EXCLOSE;
212 return (0);
213
214 case F_SETFD:
215 *pop = (*pop &~ UF_EXCLOSE) | (uap->arg & 1);
216 return (0);
217
218 case F_GETFL:
219 *retval = OFLAGS(fp->f_flag);
220 return (0);
221
222 case F_SETFL:
223 fp->f_flag &= ~FCNTLFLAGS;
224 fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
225 tmp = fp->f_flag & FNONBLOCK;
226 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
227 if (error)
228 return (error);
229 tmp = fp->f_flag & FASYNC;
230 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
231 if (!error)
232 return (0);
233 fp->f_flag &= ~FNONBLOCK;
234 tmp = 0;
235 (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
236 return (error);
237
238 case F_GETOWN:
239 if (fp->f_type == DTYPE_SOCKET)
240 cmd = SIOCGPGRP;
241 else
242 cmd = TIOCGPGRP;
243 error = (*fp->f_ops->fo_ioctl) (fp, cmd, (caddr_t)retval, p);
244 if (fp->f_type != DTYPE_SOCKET)
245 *retval = -*retval;
246 return (error);
247
248 case F_SETOWN:
249 if (fp->f_type == DTYPE_SOCKET)
250 cmd = SIOCSPGRP;
251 else {
252 cmd = TIOCSPGRP;
253 if (uap->arg <= 0) {
254 uap->arg = -uap->arg;
255 } else {
256 struct proc *p1 = pfind(uap->arg);
257 if (p1 == 0)
258 return (ESRCH);
259 uap->arg = p1->p_pgrp->pg_id;
260 }
261 }
262 return((*fp->f_ops->fo_ioctl)(fp, cmd, (caddr_t)&uap->arg, p));
263
264 case F_SETLKW:
265 flg |= F_WAIT;
266 /* Fall into F_SETLK */
267
268 case F_SETLK:
269 if (fp->f_type != DTYPE_VNODE)
270 return (EBADF);
271 vp = (struct vnode *)fp->f_data;
272
273 /* fetch the lock structure */
274 error = copyin(p, (caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
275 if (error)
276 return (error);
277
278 if (fl.l_whence == SEEK_CUR)
279 fl.l_start += fp->f_offset;
280
281 switch (fl.l_type) {
282
283 case F_RDLCK:
284 if ((fp->f_flag & FREAD) == 0)
285 return (EBADF);
286 p->p_flag |= SADVLCK;
287 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
288
289 case F_WRLCK:
290 if ((fp->f_flag & FWRITE) == 0)
291 return (EBADF);
292 p->p_flag |= SADVLCK;
293 return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
294
295 case F_UNLCK:
296 return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
297 F_POSIX));
298
299 default:
300 return (EINVAL);
301 }
302
303 case F_GETLK:
304 if (fp->f_type != DTYPE_VNODE)
305 return (EBADF);
306 vp = (struct vnode *)fp->f_data;
307
308 /* fetch the lock structure */
309 error = copyin(p, (caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
310 if (error)
311 return (error);
312 if (fl.l_whence == SEEK_CUR)
313 fl.l_start += fp->f_offset;
314 if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
315 return (error);
316 return (copyout(p, (caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
317
318 default:
319 return (EINVAL);
320 }
321 /* NOTREACHED */
322 }
323
324
325
326
327 /* POSIX close a file descriptor. */
328 int
close(p,uap,retval)329 close(p, uap, retval)
330 struct proc *p;
331 struct args {
332 int fd;
333 } *uap;
334 int *retval;
335 {
336 struct filedesc *fdp = p->p_fd;
337 struct file *fp;
338 int fd = uap->fd;
339 u_char *pf;
340
341 if ((unsigned)fd >= fdp->fd_nfiles ||
342 (fp = fdp->fd_ofiles[fd]) == NULL)
343 return (EBADF);
344
345 pf = (u_char *)&fdp->fd_ofileflags[fd];
346 if (*pf & UF_MAPPED)
347 (void) munmapfd(p, fd);
348
349 fdp->fd_ofiles[fd] = NULL;
350 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
351 fdp->fd_lastfile--;
352 if (fd < fdp->fd_freefile)
353 fdp->fd_freefile = fd;
354 *pf = 0;
355 return (closef(fp, p));
356 }
357
358
359
360 /* POSIX: Return status information about a file descriptor. */
361 int
fstat(p,uap,retval)362 fstat(p, uap, retval)
363 struct proc *p;
364 struct args {
365 int fd;
366 struct stat *sb;
367 } *uap;
368 int *retval;
369 {
370 struct filedesc *fdp = p->p_fd;
371 struct file *fp;
372 struct stat ub;
373 int error;
374
375 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
376 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
377 return (EBADF);
378
379 #ifdef foo
380 switch (fp->f_type) {
381
382 case DTYPE_VNODE:
383 error = vn_stat((struct vnode *)fp->f_data, &ub, p);
384 break;
385
386 case DTYPE_SOCKET:
387 error = soo_stat((struct socket *)fp->f_data, &ub);
388 break;
389
390 default:
391 panic("fstat");
392 /*NOTREACHED*/
393 }
394 #endif
395 error = (*fp->f_ops->fo_stat)(fp, &ub, p);
396
397 if (error == 0)
398 error = copyout(p, (caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
399 return (error);
400 }
401
402
403
404 /* POSIX Read function system call handler. */
405 int
read(p,uap,retval)406 read(p, uap, retval)
407 struct proc *p;
408 register struct args {
409 int fdes;
410 char *cbuf;
411 unsigned count;
412 } *uap;
413 int *retval;
414 {
415 register struct file *fp;
416 register struct filedesc *fdp = p->p_fd;
417 struct uio auio;
418 struct iovec aiov;
419 long cnt, error = 0;
420 #ifdef KTRACE
421 struct iovec ktriov;
422 #endif
423
424 if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
425 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
426 (fp->f_flag & FREAD) == 0)
427 return (EBADF);
428
429 aiov.iov_base = (caddr_t)uap->cbuf;
430 aiov.iov_len = uap->count;
431 auio.uio_iov = &aiov;
432 auio.uio_iovcnt = 1;
433 auio.uio_resid = uap->count;
434 auio.uio_rw = UIO_READ;
435 auio.uio_segflg = UIO_USERSPACE;
436 auio.uio_procp = p;
437
438 #ifdef KTRACE
439 /*
440 * if tracing, save a copy of iovec
441 */
442 if (KTRPOINT(p, KTR_GENIO))
443 ktriov = aiov;
444 #endif
445
446 cnt = uap->count;
447 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
448 if (auio.uio_resid != cnt && (error == ERESTART ||
449 error == EINTR || error == EWOULDBLOCK))
450 error = 0;
451 cnt -= auio.uio_resid;
452
453 #ifdef KTRACE
454 if (KTRPOINT(p, KTR_GENIO) && error == 0)
455 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error);
456 #endif
457
458 *retval = cnt;
459 return (error);
460 }
461
462
463
464 /* BSD scatter readv() system call handler. */
465 int
readv(p,uap,retval)466 readv(p, uap, retval)
467 struct proc *p;
468 register struct args {
469 int fdes;
470 struct iovec *iovp;
471 unsigned iovcnt;
472 } *uap;
473 int *retval;
474 {
475 struct file *fp;
476 struct filedesc *fdp = p->p_fd;
477 struct uio auio;
478 struct iovec *iov;
479 struct iovec *saveiov;
480 struct iovec aiov[UIO_SMALLIOV];
481 long i, cnt, error = 0;
482 unsigned iovlen;
483 #ifdef KTRACE
484 struct iovec *ktriov = NULL;
485 #endif
486
487 if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
488 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
489 (fp->f_flag & FREAD) == 0)
490 return (EBADF);
491
492 /* note: can't use iovlen until iovcnt is validated */
493 iovlen = uap->iovcnt * sizeof (struct iovec);
494
495 if (uap->iovcnt > UIO_SMALLIOV) {
496 if (uap->iovcnt > UIO_MAXIOV)
497 return (EINVAL);
498 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
499 saveiov = iov;
500 } else
501 iov = aiov;
502
503 auio.uio_iov = iov;
504 auio.uio_iovcnt = uap->iovcnt;
505 auio.uio_rw = UIO_READ;
506 auio.uio_segflg = UIO_USERSPACE;
507 auio.uio_procp = p;
508
509 if (error = copyin(p, (caddr_t)uap->iovp, (caddr_t)iov, iovlen))
510 goto done;
511
512 auio.uio_resid = 0;
513 for (i = 0; i < uap->iovcnt; i++) {
514 if (iov->iov_len < 0) {
515 error = EINVAL;
516 goto done;
517 }
518 auio.uio_resid += iov->iov_len;
519 if (auio.uio_resid < 0) {
520 error = EINVAL;
521 goto done;
522 }
523 iov++;
524 }
525
526 #ifdef KTRACE
527 /*
528 * if tracing, save a copy of iovec
529 */
530 if (KTRPOINT(p, KTR_GENIO)) {
531 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
532 (void) memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
533 }
534 #endif
535
536 cnt = auio.uio_resid;
537 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred))
538 if (auio.uio_resid != cnt && (error == ERESTART ||
539 error == EINTR || error == EWOULDBLOCK))
540 error = 0;
541 cnt -= auio.uio_resid;
542
543 #ifdef KTRACE
544 if (ktriov != NULL) {
545 if (error == 0)
546 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov,
547 cnt, error);
548 FREE(ktriov, M_TEMP);
549 }
550 #endif
551
552 *retval = cnt;
553 done:
554 if (uap->iovcnt > UIO_SMALLIOV)
555 FREE(saveiov, M_IOV);
556
557 return (error);
558 }
559
560
561
562 /* POSIX write() function system call handler */
563 int
write(p,uap,retval)564 write(p, uap, retval)
565 struct proc *p;
566 struct args {
567 int fdes;
568 char *cbuf;
569 unsigned count;
570 } *uap;
571 int *retval;
572 {
573 register struct file *fp;
574 register struct filedesc *fdp = p->p_fd;
575 struct uio auio;
576 struct iovec aiov;
577 long cnt, error = 0;
578 #ifdef KTRACE
579 struct iovec ktriov;
580 #endif
581
582 if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
583 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
584 (fp->f_flag & FWRITE) == 0)
585 return (EBADF);
586
587 aiov.iov_base = (caddr_t)uap->cbuf;
588 aiov.iov_len = uap->count;
589 auio.uio_iov = &aiov;
590 auio.uio_iovcnt = 1;
591 auio.uio_resid = uap->count;
592 auio.uio_rw = UIO_WRITE;
593 auio.uio_segflg = UIO_USERSPACE;
594 auio.uio_procp = p;
595
596 #ifdef KTRACE
597 /*
598 * if tracing, save a copy of iovec
599 */
600 if (KTRPOINT(p, KTR_GENIO))
601 ktriov = aiov;
602 #endif
603
604 cnt = uap->count;
605 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
606 if (auio.uio_resid != cnt && (error == ERESTART ||
607 error == EINTR || error == EWOULDBLOCK))
608 error = 0;
609 if (error == EPIPE)
610 psignal(p, SIGPIPE);
611 }
612 cnt -= auio.uio_resid;
613
614 #ifdef KTRACE
615 if (KTRPOINT(p, KTR_GENIO) && error == 0)
616 ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
617 &ktriov, cnt, error);
618 #endif
619
620 *retval = cnt;
621 return (error);
622 }
623
624
625
626 /* BSD gather write writev() function system call handler */
627 int
writev(p,uap,retval)628 writev(p, uap, retval)
629 struct proc *p;
630 register struct args {
631 int fdes;
632 struct iovec *iovp;
633 unsigned iovcnt;
634 } *uap;
635 int *retval;
636 {
637 register struct file *fp;
638 register struct filedesc *fdp = p->p_fd;
639 struct uio auio;
640 register struct iovec *iov;
641 struct iovec *saveiov;
642 struct iovec aiov[UIO_SMALLIOV];
643 long i, cnt, error = 0;
644 unsigned iovlen;
645 #ifdef KTRACE
646 struct iovec *ktriov = NULL;
647 #endif
648
649 if (((unsigned)uap->fdes) >= fdp->fd_nfiles ||
650 (fp = fdp->fd_ofiles[uap->fdes]) == NULL ||
651 (fp->f_flag & FWRITE) == 0)
652 return (EBADF);
653
654 /* note: can't use iovlen until iovcnt is validated */
655 iovlen = uap->iovcnt * sizeof (struct iovec);
656 if (uap->iovcnt > UIO_SMALLIOV) {
657 if (uap->iovcnt > UIO_MAXIOV)
658 return (EINVAL);
659 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
660 saveiov = iov;
661 } else
662 iov = aiov;
663
664 auio.uio_iov = iov;
665 auio.uio_iovcnt = uap->iovcnt;
666 auio.uio_rw = UIO_WRITE;
667 auio.uio_segflg = UIO_USERSPACE;
668 auio.uio_procp = p;
669
670 if (error = copyin(p, (caddr_t)uap->iovp, (caddr_t)iov, iovlen))
671 goto done;
672
673 auio.uio_resid = 0;
674 for (i = 0; i < uap->iovcnt; i++) {
675 if (iov->iov_len < 0) {
676 error = EINVAL;
677 goto done;
678 }
679 auio.uio_resid += iov->iov_len;
680 if (auio.uio_resid < 0) {
681 error = EINVAL;
682 goto done;
683 }
684 iov++;
685 }
686
687 #ifdef KTRACE
688 /*
689 * if tracing, save a copy of iovec
690 */
691 if (KTRPOINT(p, KTR_GENIO)) {
692 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
693 (void) memcpy((caddr_t)ktriov, (caddr_t)auio.uio_iov, iovlen);
694 }
695 #endif
696
697 cnt = auio.uio_resid;
698 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) {
699 if (auio.uio_resid != cnt && (error == ERESTART ||
700 error == EINTR || error == EWOULDBLOCK))
701 error = 0;
702 if (error == EPIPE)
703 psignal(p, SIGPIPE);
704 }
705 cnt -= auio.uio_resid;
706
707 #ifdef KTRACE
708 if (ktriov != NULL) {
709 if (error == 0)
710 ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE,
711 ktriov, cnt, error);
712 FREE(ktriov, M_TEMP);
713 }
714 #endif
715
716 *retval = cnt;
717 done:
718 if (uap->iovcnt > UIO_SMALLIOV)
719 FREE(saveiov, M_IOV);
720
721 return (error);
722 }
723
724
725
726
727 /* POSIX ioctl() function system call handler */
728 int
ioctl(p,uap,retval)729 ioctl(p, uap, retval)
730 struct proc *p;
731 register struct args {
732 int fdes;
733 int cmd;
734 caddr_t cmarg;
735 } *uap;
736 int *retval;
737 {
738 struct file *fp;
739 struct filedesc *fdp = p->p_fd;
740 int com, cmd, error;
741 u_int size;
742 caddr_t memp = 0;
743 #define STK_PARAMS 128
744 char stkbuf[STK_PARAMS];
745 caddr_t data = stkbuf;
746 int tmp;
747
748 if ((unsigned)uap->fdes >= fdp->fd_nfiles ||
749 (fp = fdp->fd_ofiles[uap->fdes]) == NULL)
750 return (EBADF);
751 if ((fp->f_flag & (FREAD|FWRITE)) == 0)
752 return (EBADF);
753
754 com = uap->cmd;
755 if (com == FIOCLEX) {
756 fdp->fd_ofileflags[uap->fdes] |= UF_EXCLOSE;
757 return (0);
758 }
759 if (com == FIONCLEX) {
760 fdp->fd_ofileflags[uap->fdes] &= ~UF_EXCLOSE;
761 return (0);
762 }
763
764 /*
765 * Interpret high order word to find
766 * amount of data to be copied to/from the
767 * user's address space.
768 */
769 size = IOCPARM_LEN(com);
770 if (size > IOCPARM_MAX)
771 return (ENOTTY);
772 if (size > sizeof (stkbuf)) {
773 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
774 data = memp;
775 }
776 if (com&IOC_IN) {
777 if (size) {
778 error = copyin(p, uap->cmarg, data, (u_int)size);
779 if (error) {
780 if (memp)
781 free(memp, M_IOCTLOPS);
782 return (error);
783 }
784 } else
785 *(caddr_t *)data = uap->cmarg;
786 } else if ((com&IOC_OUT) && size)
787 /*
788 * Zero the buffer so the user always
789 * gets back something deterministic.
790 */
791 (void) memset(data, 0, size);
792 else if (com&IOC_VOID)
793 *(caddr_t *)data = uap->cmarg;
794
795 switch (com) {
796
797 case FIONBIO:
798 if (tmp = *(int *)data)
799 fp->f_flag |= FNONBLOCK;
800 else
801 fp->f_flag &= ~FNONBLOCK;
802 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
803 break;
804
805 case FIOASYNC:
806 if (tmp = *(int *)data)
807 fp->f_flag |= FASYNC;
808 else
809 fp->f_flag &= ~FASYNC;
810 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
811 break;
812
813 case FIOSETOWN:
814 tmp = *(int *)data;
815 if (fp->f_type == DTYPE_SOCKET)
816 cmd = SIOCSPGRP;
817 else {
818 cmd = TIOCSPGRP;
819 if (tmp <= 0) {
820 tmp = -tmp;
821 } else {
822 struct proc *p1 = pfind(tmp);
823 if (p1 == 0) {
824 error = ESRCH;
825 break;
826 }
827 tmp = p1->p_pgrp->pg_id;
828 }
829 }
830 error = (*fp->f_ops->fo_ioctl) (fp, cmd, (caddr_t)&tmp, p);
831 break;
832
833 case FIOGETOWN:
834 if (fp->f_type == DTYPE_SOCKET)
835 cmd = SIOCGPGRP;
836 else
837 cmd = TIOCGPGRP;
838 error = (*fp->f_ops->fo_ioctl)(fp, cmd, data, p);
839 if (fp->f_type != DTYPE_SOCKET)
840 *(int *)data = -*(int *)data;
841 break;
842
843 default:
844 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p);
845 if (error == 0 && (com&IOC_OUT) && size)
846 error = copyout(p, data, uap->cmarg, (u_int)size);
847 break;
848 }
849
850 if (memp)
851 free(memp, M_IOCTLOPS);
852 return (error);
853 }
854
855 int selwait, nselcoll;
856
857
858
859 /* BSD select() function system call handler. */
860 int
select(p,uap,retval)861 select(p, uap, retval)
862 register struct proc *p;
863 register struct args {
864 int nd;
865 fd_set *in, *ou, *ex;
866 struct timeval *tv;
867 } *uap;
868 int *retval;
869 {
870 fd_set ibits[3], obits[3];
871 struct timeval atv;
872 int ncoll, ni, error = 0, timo;
873
874 (void) memset((caddr_t)ibits, 0, sizeof(ibits));
875 (void) memset((caddr_t)obits, 0, sizeof(obits));
876 if (uap->nd > p->p_fd->fd_nfiles)
877 uap->nd = p->p_fd->fd_nfiles;
878 ni = howmany(uap->nd, NFDBITS);
879
880 #define getbits(name, x) \
881 if (uap->name) { \
882 error = copyin(p, (caddr_t)uap->name, (caddr_t)&ibits[x], \
883 (unsigned)(ni * sizeof(fd_mask))); \
884 if (error) \
885 goto done; \
886 }
887 getbits(in, 0);
888 getbits(ou, 1);
889 getbits(ex, 2);
890 #undef getbits
891
892 if (uap->tv) {
893 error = copyin(p, (caddr_t)uap->tv, (caddr_t)&atv,
894 sizeof (atv));
895 if (error)
896 goto done;
897 if (itimerfix(&atv)) {
898 error = EINVAL;
899 goto done;
900 }
901 splclock(); timevaladd(&atv, &time); splnone();
902 timo = hzto(&atv);
903 } else
904 timo = 0;
905
906 retry:
907 ncoll = nselcoll;
908 p->p_flag |= SSEL;
909 error = selscan(p, ibits, obits, uap->nd, retval);
910 if (error || *retval)
911 goto done;
912
913 splhigh();
914 /* this should be timercmp(&time, &atv, >=) */
915 if (uap->tv && (time.tv_sec > atv.tv_sec ||
916 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) {
917 p->p_flag &= ~SSEL;
918 /* error = EWOULDBLOCK; */
919 splnone();
920 goto done;
921 }
922 if ((p->p_flag & SSEL) == 0 || nselcoll != ncoll) {
923 splnone();
924 goto retry;
925 }
926 p->p_flag &= ~SSEL;
927 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo);
928 splnone();
929
930 if (error == 0)
931 goto retry;
932 done:
933
934 /* select is not restarted after signals... */
935 if (error == ERESTART)
936 error = EINTR;
937 if (error == EWOULDBLOCK)
938 error = 0;
939
940 #define putbits(name, x) \
941 if (uap->name) { \
942 int error2 = copyout(p, (caddr_t)&obits[x], (caddr_t)uap->name, \
943 (unsigned)(ni * sizeof(fd_mask))); \
944 if (error2) \
945 error = error2; \
946 }
947 if (error == 0) {
948 putbits(in, 0);
949 putbits(ou, 1);
950 putbits(ex, 2);
951 }
952 #undef putbits
953
954 return (error);
955 }
956
957 static int
selscan(struct proc * p,fd_set * ibits,fd_set * obits,int nfd,int * retval)958 selscan(struct proc *p, fd_set *ibits, fd_set *obits, int nfd, int *retval)
959 {
960 struct filedesc *fdp = p->p_fd;
961 int which, i, j;
962 fd_mask bits;
963 int flag;
964 struct file *fp;
965 int error = 0, n = 0;
966
967 for (which = 0; which < 3; which++) {
968 switch (which) {
969
970 case 0:
971 flag = FREAD; break;
972
973 case 1:
974 flag = FWRITE; break;
975
976 case 2:
977 flag = 0; break;
978 }
979 for (i = 0; i < nfd; i += NFDBITS) {
980 bits = ibits[which].fds_bits[i/NFDBITS];
981 while ((j = ffs(bits)) && i + --j < nfd) {
982 bits &= ~(1 << j);
983 fp = fdp->fd_ofiles[i + j];
984 if (fp == NULL) {
985 error = EBADF;
986 break;
987 }
988 if ((*fp->f_ops->fo_select)(fp, flag, p)) {
989 FD_SET(i + j, &obits[which]);
990 n++;
991 }
992 }
993 }
994 }
995 *retval = n;
996 return (error);
997 }
998
999 /*ARGSUSED*/
1000 int
seltrue(dev_t dev,int which,struct proc * p)1001 seltrue(dev_t dev, int which, struct proc *p)
1002 {
1003
1004 return (1);
1005 }
1006
1007
1008 void
selwakeup(pid_t pid,int coll)1009 selwakeup(pid_t pid, int coll)
1010 {
1011 register struct proc *p;
1012
1013 if (coll) {
1014 nselcoll++;
1015 wakeup((caddr_t)&selwait);
1016 }
1017
1018 if (pid && (p = pfind(pid))) {
1019 int s = splhigh();
1020
1021 if (p->p_wchan == (caddr_t)&selwait) {
1022 if (p->p_stat == SSLEEP)
1023 setrun(p);
1024 else
1025 unsleep(p);
1026 } else if (p->p_flag & SSEL)
1027 p->p_flag &= ~SSEL;
1028 splx(s);
1029 }
1030 }
1031
1032 /*
1033 * Allocate a file descriptor for the process.
1034 */
1035 int
fdalloc(struct proc * p,int want,int * result)1036 fdalloc(struct proc *p, int want, int *result)
1037 {
1038 register struct filedesc *fdp = p->p_fd;
1039 int i;
1040 int lim, last, nfiles;
1041 struct file **newofile;
1042 char *newofileflags;
1043
1044 /*
1045 * Search for a free descriptor starting at the higher
1046 * of want or fd_freefile. If that fails, consider
1047 * expanding the ofile array.
1048 */
1049 lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
1050 for (;;) {
1051 last = min(fdp->fd_nfiles, lim);
1052 if ((i = want) < fdp->fd_freefile)
1053 i = fdp->fd_freefile;
1054 for (; i < last; i++) {
1055 if (fdp->fd_ofiles[i] == NULL) {
1056 fdp->fd_ofileflags[i] = 0;
1057 if (i > fdp->fd_lastfile)
1058 fdp->fd_lastfile = i;
1059 if (want <= fdp->fd_freefile)
1060 fdp->fd_freefile = i;
1061 *result = i;
1062 return (0);
1063 }
1064 }
1065
1066 /* no space in current array. expand it? */
1067 if (fdp->fd_nfiles >= lim)
1068 return (EMFILE);
1069 if (fdp->fd_nfiles < NDEXTENT)
1070 nfiles = NDEXTENT;
1071 else
1072 nfiles = (2 * fdp->fd_nfiles) % lim;
1073
1074 MALLOC(newofile, struct file **, nfiles * OFILESIZE,
1075 M_FILEDESC, M_WAITOK);
1076 newofileflags = (char *) &newofile[nfiles];
1077
1078 /*
1079 * Copy the existing ofile and ofileflags arrays
1080 * and zero the new portion of each array.
1081 */
1082 (void) memcpy(newofile, fdp->fd_ofiles,
1083 (i = sizeof(struct file *) * fdp->fd_nfiles));
1084 (void) memset((char *)newofile + i, 0,
1085 nfiles * sizeof(struct file *) - i);
1086 (void) memcpy(newofileflags, fdp->fd_ofileflags,
1087 (i = sizeof(char) * fdp->fd_nfiles));
1088 (void) memset(newofileflags + i, 0, nfiles * sizeof(char) - i);
1089
1090 if (fdp->fd_nfiles > NDFILE)
1091 FREE(fdp->fd_ofiles, M_FILEDESC);
1092
1093 fdp->fd_ofiles = newofile;
1094 fdp->fd_ofileflags = newofileflags;
1095 fdp->fd_nfiles = nfiles;
1096 }
1097 }
1098
1099 /*
1100 * Check to see whether n user file descriptors
1101 * are available to the process p.
1102 */
1103 int
fdavail(struct proc * p,int n)1104 fdavail(struct proc *p, int n)
1105 {
1106 struct filedesc *fdp = p->p_fd;
1107 struct file **fpp;
1108 int i;
1109
1110 if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 &&
1111 (n -= i) <= 0)
1112 return (1);
1113
1114 fpp = &fdp->fd_ofiles[fdp->fd_freefile];
1115 for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
1116 if (*fpp == NULL && --n <= 0)
1117 return (1);
1118 return (0);
1119 }
1120
1121 /*
1122 * Create a new open file structure and allocate
1123 * a file descriptor for the process that refers to it.
1124 */
1125 int
falloc(struct proc * p,struct file ** resultfp,int * resultfd)1126 falloc(struct proc *p, struct file **resultfp, int *resultfd)
1127 {
1128 struct file *fp, *fq, **fpp;
1129 int error, i;
1130
1131 if (error = fdalloc(p, 0, &i))
1132 return (error);
1133 if (nfiles >= maxfiles) {
1134 tablefull("file");
1135 return (ENFILE);
1136 }
1137
1138 /*
1139 * Allocate a new file descriptor.
1140 * If the process has file descriptor zero open, add to the list
1141 * of open files at that point, otherwise put it at the front of
1142 * the list of open files.
1143 */
1144 nfiles++;
1145 MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
1146 if (fq = p->p_fd->fd_ofiles[0])
1147 fpp = &fq->f_filef;
1148 else
1149 fpp = &filehead;
1150 p->p_fd->fd_ofiles[i] = fp;
1151 if (fq = *fpp)
1152 fq->f_fileb = &fp->f_filef;
1153 fp->f_filef = fq;
1154 fp->f_fileb = fpp;
1155 *fpp = fp;
1156
1157 fp->f_count = 1;
1158 fp->f_msgcount = 0;
1159 fp->f_offset = 0;
1160 fp->f_cred = p->p_ucred;
1161 crhold(fp->f_cred);
1162
1163 if (resultfp)
1164 *resultfp = fp;
1165 if (resultfd)
1166 *resultfd = i;
1167 return (0);
1168 }
1169
1170 /*
1171 * Free a file instance, recovering resources.
1172 */
1173 void
ffree(struct file * fp)1174 ffree(struct file *fp)
1175 {
1176 struct file *fq;
1177
1178 /* remove from global file list */
1179 if (fq = fp->f_filef)
1180 fq->f_fileb = fp->f_fileb;
1181 *fp->f_fileb = fq;
1182
1183 #ifdef DIAGNOSTIC
1184 fp->f_filef = NULL;
1185 fp->f_fileb = NULL;
1186 fp->f_count = 0;
1187 #endif
1188
1189 crfree(fp->f_cred);
1190 nfiles--;
1191 FREE(fp, M_FILE);
1192 }
1193
1194 /*
1195 * Copy a filedesc structure.
1196 */
1197 struct filedesc *
fdcopy(struct proc * p)1198 fdcopy(struct proc *p)
1199 {
1200 struct filedesc *newfdp, *fdp = p->p_fd;
1201 struct file **fpp;
1202 int i;
1203
1204 MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
1205 M_FILEDESC, M_WAITOK);
1206 (void) memcpy(newfdp, fdp, sizeof(struct filedesc));
1207 newfdp->fd_refcnt = 1;
1208
1209 VREF(newfdp->fd_cdir);
1210 if (newfdp->fd_rdir)
1211 VREF(newfdp->fd_rdir);
1212
1213 /*
1214 * If the number of open files fits in the internal arrays
1215 * of the open file structure, use them, otherwise allocate
1216 * additional memory for the number of descriptors currently
1217 * in use.
1218 */
1219 if (newfdp->fd_lastfile < NDFILE) {
1220 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
1221 newfdp->fd_ofileflags =
1222 ((struct filedesc0 *) newfdp)->fd_dfileflags;
1223 i = NDFILE;
1224 } else {
1225 /*
1226 * Compute the smallest multiple of NDEXTENT needed
1227 * for the file descriptors currently in use,
1228 * allowing the table to shrink.
1229 */
1230 i = newfdp->fd_nfiles;
1231 while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2)
1232 i /= 2;
1233 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
1234 M_FILEDESC, M_WAITOK);
1235 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
1236 }
1237
1238 newfdp->fd_nfiles = i;
1239 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles, i * sizeof(struct file **));
1240 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags, i * sizeof(char));
1241 fpp = newfdp->fd_ofiles;
1242 for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
1243 if (*fpp != NULL)
1244 (*fpp)->f_count++;
1245
1246 return (newfdp);
1247 }
1248
1249 /*
1250 * Release a filedesc structure.
1251 */
1252 void
fdfree(struct proc * p)1253 fdfree(struct proc *p)
1254 {
1255 register struct filedesc *fdp = p->p_fd;
1256 struct file **fpp;
1257 char *fdfp;
1258 register int i;
1259
1260 if (--fdp->fd_refcnt > 0)
1261 return;
1262
1263 fpp = fdp->fd_ofiles;
1264 fdfp = fdp->fd_ofileflags;
1265 for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++)
1266 if (*fpp != NULL) {
1267 if (*fdfp & UF_MAPPED)
1268 (void) munmapfd(p, i);
1269 (void) closef(*fpp, p);
1270 }
1271
1272 if (fdp->fd_nfiles > NDFILE)
1273 FREE(fdp->fd_ofiles, M_FILEDESC);
1274
1275 vrele(fdp->fd_cdir);
1276 if (fdp->fd_rdir)
1277 vrele(fdp->fd_rdir);
1278
1279 FREE(fdp, M_FILEDESC);
1280 }
1281
1282 /* Close any files on execve()? */
1283 void
fdcloseexec(struct proc * p)1284 fdcloseexec(struct proc *p)
1285 {
1286 struct filedesc *fdp = p->p_fd;
1287 struct file **fpp;
1288 char *fdfp;
1289 register int i;
1290
1291 fpp = fdp->fd_ofiles;
1292 fdfp = fdp->fd_ofileflags;
1293 for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++)
1294 if (*fpp != NULL && (*fdfp & UF_EXCLOSE)) {
1295 if (*fdfp & UF_MAPPED)
1296 (void) munmapfd(p, i);
1297 (void) closef(*fpp, p);
1298 *fpp = NULL;
1299 *fdfp = 0;
1300 if (i < fdp->fd_freefile)
1301 fdp->fd_freefile = i;
1302 }
1303
1304 while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
1305 fdp->fd_lastfile--;
1306 }
1307
1308 /*
1309 * Private file close function.
1310 * Decrement reference count on file structure.
1311 */
1312 int
closef(struct file * fp,struct proc * p)1313 closef(struct file *fp, struct proc *p)
1314 {
1315 struct vnode *vp;
1316 struct flock lf;
1317 int error;
1318
1319 if (fp == NULL)
1320 return (0);
1321 /*
1322 * POSIX record locking dictates that any close releases ALL
1323 * locks owned by this process. This is handled by setting
1324 * a flag in the unlock to free ONLY locks obeying POSIX
1325 * semantics, and not to free BSD-style file locks.
1326 */
1327 if ((p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) {
1328 lf.l_whence = SEEK_SET;
1329 lf.l_start = 0;
1330 lf.l_len = 0;
1331 lf.l_type = F_UNLCK;
1332 vp = (struct vnode *)fp->f_data;
1333 (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
1334 }
1335 if (--fp->f_count > 0)
1336 return (0);
1337
1338 #ifdef DIAGNOSTIC
1339 if (fp->f_count < 0)
1340 panic("closef: count < 0");
1341 #endif
1342 if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1343 lf.l_whence = SEEK_SET;
1344 lf.l_start = 0;
1345 lf.l_len = 0;
1346 lf.l_type = F_UNLCK;
1347 vp = (struct vnode *)fp->f_data;
1348 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1349 }
1350
1351 error = (*fp->f_ops->fo_close)(fp, p);
1352 ffree(fp);
1353 return (error);
1354 }
1355
1356 /*
1357 * Apply an advisory lock on a file descriptor.
1358 *
1359 * Just attempt to get a record lock of the requested type on
1360 * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1361 */
1362
1363 /* ARGSUSED */
1364 int
flock(p,uap,retval)1365 flock(p, uap, retval)
1366 struct proc *p;
1367 struct args {
1368 int fd;
1369 int how;
1370 } *uap;
1371 int *retval;
1372 {
1373 register struct filedesc *fdp = p->p_fd;
1374 register struct file *fp;
1375 struct vnode *vp;
1376 struct flock lf;
1377 int error;
1378
1379 if ((unsigned)uap->fd >= fdp->fd_nfiles ||
1380 (fp = fdp->fd_ofiles[uap->fd]) == NULL)
1381 return (EBADF);
1382 if (fp->f_type != DTYPE_VNODE)
1383 return (EOPNOTSUPP);
1384
1385 vp = (struct vnode *)fp->f_data;
1386 lf.l_whence = SEEK_SET;
1387 lf.l_start = 0;
1388 lf.l_len = 0;
1389
1390 if (uap->how & LOCK_UN) {
1391 lf.l_type = F_UNLCK;
1392 fp->f_flag &= ~FHASLOCK;
1393 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
1394 }
1395
1396 if (uap->how & LOCK_EX)
1397 lf.l_type = F_WRLCK;
1398 else if (uap->how & LOCK_SH)
1399 lf.l_type = F_RDLCK;
1400 else
1401 return (EBADF);
1402
1403 fp->f_flag |= FHASLOCK;
1404 if (uap->how & LOCK_NB)
1405 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
1406
1407 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
1408 }
1409
1410 /*
1411 * File Descriptor pseudo-device driver (/dev/fd/).
1412 *
1413 * Opening minor device N dup()s the file (if any) connected to file
1414 * descriptor N belonging to the calling process. Note that this driver
1415 * consists of only the ``open()'' routine, because all subsequent
1416 * references to this file will be directed to the other file.
1417 */
1418 /* ARGSUSED */
1419 static int
fdopen(dev_t dev,int mode,int type,struct proc * p)1420 fdopen(dev_t dev, int mode, int type, struct proc *p)
1421 {
1422
1423 /*
1424 * XXX Kludge: set curproc->p_dupfd to contain the value of the
1425 * the file descriptor being sought for duplication. The error
1426 * return ensures that the vnode for this device will be released
1427 * by vn_open. Open will detect this special error and take the
1428 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1429 * will simply report the error.
1430 */
1431 p->p_dupfd = minor(dev); /* XXX */
1432 return (ENODEV);
1433 }
1434
1435 static struct devif fd_devif =
1436 {
1437 {0}, -1, -2, 0, 0, 0, 0, 0, 0,
1438 fdopen, 0, 0, 0, 0, 0, 0,
1439 0, 0, 0, 0,
1440 0, 0,
1441 };
1442
DRIVER_MODCONFIG()1443 DRIVER_MODCONFIG() {
1444 char *cfg_string = "fdesc 53.";
1445
1446 if (devif_config(&cfg_string, &fd_devif) == 0)
1447 return;
1448 }
1449
1450 /*
1451 * Duplicate the specified descriptor to a free descriptor.
1452 */
1453 int
dupfdopen(struct filedesc * fdp,int indx,int dfd,int mode)1454 dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode)
1455 {
1456 register struct file *wfp;
1457 struct file *fp;
1458
1459 /*
1460 * If the to-be-dup'd fd number is greater than the allowed number
1461 * of file descriptors, or the fd to be dup'd has already been
1462 * closed, reject. Note, check for new == old is necessary as
1463 * falloc could allocate an already closed to-be-dup'd descriptor
1464 * as the new descriptor.
1465 */
1466 fp = fdp->fd_ofiles[indx];
1467 if ((u_int)dfd >= fdp->fd_nfiles ||
1468 (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
1469 return (EBADF);
1470
1471 /*
1472 * Check that the mode the file is being opened for is a subset
1473 * of the mode of the existing descriptor.
1474 */
1475 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
1476 return (EACCES);
1477 fdp->fd_ofiles[indx] = wfp;
1478 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1479 wfp->f_count++;
1480 if (indx > fdp->fd_lastfile)
1481 fdp->fd_lastfile = indx;
1482 return (0);
1483 }
1484