| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: sys_generic.c,v 1.123 2009/05/24 21:41:26 ad Exp $ */ | | 1 | /* $NetBSD: sys_generic.c,v 1.124 2009/08/13 08:57:43 haad Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Andrew Doran. | | 8 | * by Andrew Doran. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -60,27 +60,27 @@ | | | @@ -60,27 +60,27 @@ |
60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 60 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 61 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 62 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
63 | * SUCH DAMAGE. | | 63 | * SUCH DAMAGE. |
64 | * | | 64 | * |
65 | * @(#)sys_generic.c 8.9 (Berkeley) 2/14/95 | | 65 | * @(#)sys_generic.c 8.9 (Berkeley) 2/14/95 |
66 | */ | | 66 | */ |
67 | | | 67 | |
68 | /* | | 68 | /* |
69 | * System calls relating to files. | | 69 | * System calls relating to files. |
70 | */ | | 70 | */ |
71 | | | 71 | |
72 | #include <sys/cdefs.h> | | 72 | #include <sys/cdefs.h> |
73 | __KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.123 2009/05/24 21:41:26 ad Exp $"); | | 73 | __KERNEL_RCSID(0, "$NetBSD: sys_generic.c,v 1.124 2009/08/13 08:57:43 haad Exp $"); |
74 | | | 74 | |
75 | #include <sys/param.h> | | 75 | #include <sys/param.h> |
76 | #include <sys/systm.h> | | 76 | #include <sys/systm.h> |
77 | #include <sys/filedesc.h> | | 77 | #include <sys/filedesc.h> |
78 | #include <sys/ioctl.h> | | 78 | #include <sys/ioctl.h> |
79 | #include <sys/file.h> | | 79 | #include <sys/file.h> |
80 | #include <sys/proc.h> | | 80 | #include <sys/proc.h> |
81 | #include <sys/socketvar.h> | | 81 | #include <sys/socketvar.h> |
82 | #include <sys/signalvar.h> | | 82 | #include <sys/signalvar.h> |
83 | #include <sys/uio.h> | | 83 | #include <sys/uio.h> |
84 | #include <sys/kernel.h> | | 84 | #include <sys/kernel.h> |
85 | #include <sys/stat.h> | | 85 | #include <sys/stat.h> |
86 | #include <sys/kmem.h> | | 86 | #include <sys/kmem.h> |
| @@ -555,51 +555,60 @@ sys_ioctl(struct lwp *l, const struct sy | | | @@ -555,51 +555,60 @@ sys_ioctl(struct lwp *l, const struct sy |
555 | goto out; | | 555 | goto out; |
556 | } | | 556 | } |
557 | | | 557 | |
558 | /* | | 558 | /* |
559 | * Interpret high order word to find amount of data to be | | 559 | * Interpret high order word to find amount of data to be |
560 | * copied to/from the user's address space. | | 560 | * copied to/from the user's address space. |
561 | */ | | 561 | */ |
562 | size = IOCPARM_LEN(com); | | 562 | size = IOCPARM_LEN(com); |
563 | if (size > IOCPARM_MAX) { | | 563 | if (size > IOCPARM_MAX) { |
564 | error = ENOTTY; | | 564 | error = ENOTTY; |
565 | goto out; | | 565 | goto out; |
566 | } | | 566 | } |
567 | memp = NULL; | | 567 | memp = NULL; |
568 | if (size > sizeof(stkbuf)) { | | 568 | if ((com >> IOCPARM_SHIFT) == 0) { |
569 | memp = kmem_alloc(size, KM_SLEEP); | | 569 | /* UNIX-style ioctl. */ |
570 | data = memp; | | 570 | data = SCARG(uap, data); |
571 | } else | | 571 | } else { |
572 | data = (void *)stkbuf; | | 572 | if (size > sizeof(stkbuf)) { |
573 | if (com&IOC_IN) { | | 573 | memp = kmem_alloc(size, KM_SLEEP); |
574 | if (size) { | | 574 | data = memp; |
575 | error = copyin(SCARG(uap, data), data, size); | | 575 | } else { |
576 | if (error) { | | 576 | data = (void *)stkbuf; |
577 | if (memp) | | 577 | } |
578 | kmem_free(memp, size); | | 578 | if (com&IOC_IN) { |
579 | goto out; | | 579 | if (size) { |
| | | 580 | error = copyin(SCARG(uap, data), data, size); |
| | | 581 | if (error) { |
| | | 582 | if (memp) { |
| | | 583 | kmem_free(memp, size); |
| | | 584 | } |
| | | 585 | goto out; |
| | | 586 | } |
| | | 587 | ktrgenio(SCARG(uap, fd), UIO_WRITE, |
| | | 588 | SCARG(uap, data), size, 0); |
| | | 589 | } else { |
| | | 590 | *(void **)data = SCARG(uap, data); |
580 | } | | 591 | } |
581 | ktrgenio(SCARG(uap, fd), UIO_WRITE, SCARG(uap, data), | | 592 | } else if ((com&IOC_OUT) && size) { |
582 | size, 0); | | 593 | /* |
583 | } else | | 594 | * Zero the buffer so the user always |
| | | 595 | * gets back something deterministic. |
| | | 596 | */ |
| | | 597 | memset(data, 0, size); |
| | | 598 | } else if (com&IOC_VOID) { |
584 | *(void **)data = SCARG(uap, data); | | 599 | *(void **)data = SCARG(uap, data); |
585 | } else if ((com&IOC_OUT) && size) | | 600 | } |
586 | /* | | 601 | } |
587 | * Zero the buffer so the user always | | | |
588 | * gets back something deterministic. | | | |
589 | */ | | | |
590 | memset(data, 0, size); | | | |
591 | else if (com&IOC_VOID) | | | |
592 | *(void **)data = SCARG(uap, data); | | | |
593 | | | 602 | |
594 | switch (com) { | | 603 | switch (com) { |
595 | | | 604 | |
596 | case FIONBIO: | | 605 | case FIONBIO: |
597 | /* XXX Code block is not atomic */ | | 606 | /* XXX Code block is not atomic */ |
598 | if (*(int *)data != 0) | | 607 | if (*(int *)data != 0) |
599 | atomic_or_uint(&fp->f_flag, FNONBLOCK); | | 608 | atomic_or_uint(&fp->f_flag, FNONBLOCK); |
600 | else | | 609 | else |
601 | atomic_and_uint(&fp->f_flag, ~FNONBLOCK); | | 610 | atomic_and_uint(&fp->f_flag, ~FNONBLOCK); |
602 | error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, data); | | 611 | error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, data); |
603 | break; | | 612 | break; |
604 | | | 613 | |
605 | case FIOASYNC: | | 614 | case FIOASYNC: |