diff options
| -rw-r--r-- | drivers/char/lp.c | 115 | ||||
| -rw-r--r-- | fs/compat_ioctl.c | 33 |
2 files changed, 89 insertions, 59 deletions
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index e444c2dba160..938a3a273886 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
| @@ -127,6 +127,7 @@ | |||
| 127 | #include <linux/wait.h> | 127 | #include <linux/wait.h> |
| 128 | #include <linux/jiffies.h> | 128 | #include <linux/jiffies.h> |
| 129 | #include <linux/smp_lock.h> | 129 | #include <linux/smp_lock.h> |
| 130 | #include <linux/compat.h> | ||
| 130 | 131 | ||
| 131 | #include <linux/parport.h> | 132 | #include <linux/parport.h> |
| 132 | #undef LP_STATS | 133 | #undef LP_STATS |
| @@ -571,13 +572,11 @@ static int lp_release(struct inode * inode, struct file * file) | |||
| 571 | return 0; | 572 | return 0; |
| 572 | } | 573 | } |
| 573 | 574 | ||
| 574 | static int lp_ioctl(struct inode *inode, struct file *file, | 575 | static int lp_do_ioctl(unsigned int minor, unsigned int cmd, |
| 575 | unsigned int cmd, unsigned long arg) | 576 | unsigned long arg, void __user *argp) |
| 576 | { | 577 | { |
| 577 | unsigned int minor = iminor(inode); | ||
| 578 | int status; | 578 | int status; |
| 579 | int retval = 0; | 579 | int retval = 0; |
| 580 | void __user *argp = (void __user *)arg; | ||
| 581 | 580 | ||
| 582 | #ifdef LP_DEBUG | 581 | #ifdef LP_DEBUG |
| 583 | printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); | 582 | printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); |
| @@ -587,9 +586,6 @@ static int lp_ioctl(struct inode *inode, struct file *file, | |||
| 587 | if ((LP_F(minor) & LP_EXIST) == 0) | 586 | if ((LP_F(minor) & LP_EXIST) == 0) |
| 588 | return -ENODEV; | 587 | return -ENODEV; |
| 589 | switch ( cmd ) { | 588 | switch ( cmd ) { |
| 590 | struct timeval par_timeout; | ||
| 591 | long to_jiffies; | ||
| 592 | |||
| 593 | case LPTIME: | 589 | case LPTIME: |
| 594 | LP_TIME(minor) = arg * HZ/100; | 590 | LP_TIME(minor) = arg * HZ/100; |
| 595 | break; | 591 | break; |
| @@ -652,34 +648,101 @@ static int lp_ioctl(struct inode *inode, struct file *file, | |||
| 652 | return -EFAULT; | 648 | return -EFAULT; |
| 653 | break; | 649 | break; |
| 654 | 650 | ||
| 655 | case LPSETTIMEOUT: | ||
| 656 | if (copy_from_user (&par_timeout, argp, | ||
| 657 | sizeof (struct timeval))) { | ||
| 658 | return -EFAULT; | ||
| 659 | } | ||
| 660 | /* Convert to jiffies, place in lp_table */ | ||
| 661 | if ((par_timeout.tv_sec < 0) || | ||
| 662 | (par_timeout.tv_usec < 0)) { | ||
| 663 | return -EINVAL; | ||
| 664 | } | ||
| 665 | to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ); | ||
| 666 | to_jiffies += par_timeout.tv_sec * (long) HZ; | ||
| 667 | if (to_jiffies <= 0) { | ||
| 668 | return -EINVAL; | ||
| 669 | } | ||
| 670 | lp_table[minor].timeout = to_jiffies; | ||
| 671 | break; | ||
| 672 | |||
| 673 | default: | 651 | default: |
| 674 | retval = -EINVAL; | 652 | retval = -EINVAL; |
| 675 | } | 653 | } |
| 676 | return retval; | 654 | return retval; |
| 677 | } | 655 | } |
| 678 | 656 | ||
| 657 | static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout) | ||
| 658 | { | ||
| 659 | long to_jiffies; | ||
| 660 | |||
| 661 | /* Convert to jiffies, place in lp_table */ | ||
| 662 | if ((par_timeout->tv_sec < 0) || | ||
| 663 | (par_timeout->tv_usec < 0)) { | ||
| 664 | return -EINVAL; | ||
| 665 | } | ||
| 666 | to_jiffies = DIV_ROUND_UP(par_timeout->tv_usec, 1000000/HZ); | ||
| 667 | to_jiffies += par_timeout->tv_sec * (long) HZ; | ||
| 668 | if (to_jiffies <= 0) { | ||
| 669 | return -EINVAL; | ||
| 670 | } | ||
| 671 | lp_table[minor].timeout = to_jiffies; | ||
| 672 | return 0; | ||
| 673 | } | ||
| 674 | |||
| 675 | static long lp_ioctl(struct file *file, unsigned int cmd, | ||
| 676 | unsigned long arg) | ||
| 677 | { | ||
| 678 | unsigned int minor; | ||
| 679 | struct timeval par_timeout; | ||
| 680 | int ret; | ||
| 681 | |||
| 682 | minor = iminor(file->f_path.dentry->d_inode); | ||
| 683 | lock_kernel(); | ||
| 684 | switch (cmd) { | ||
| 685 | case LPSETTIMEOUT: | ||
| 686 | if (copy_from_user(&par_timeout, (void __user *)arg, | ||
| 687 | sizeof (struct timeval))) { | ||
| 688 | ret = -EFAULT; | ||
| 689 | break; | ||
| 690 | } | ||
| 691 | ret = lp_set_timeout(minor, &par_timeout); | ||
| 692 | break; | ||
| 693 | default: | ||
| 694 | ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg); | ||
| 695 | break; | ||
| 696 | } | ||
| 697 | unlock_kernel(); | ||
| 698 | |||
| 699 | return ret; | ||
| 700 | } | ||
| 701 | |||
| 702 | #ifdef CONFIG_COMPAT | ||
| 703 | static long lp_compat_ioctl(struct file *file, unsigned int cmd, | ||
| 704 | unsigned long arg) | ||
| 705 | { | ||
| 706 | unsigned int minor; | ||
| 707 | struct timeval par_timeout; | ||
| 708 | struct compat_timeval __user *tc; | ||
| 709 | int ret; | ||
| 710 | |||
| 711 | minor = iminor(file->f_path.dentry->d_inode); | ||
| 712 | lock_kernel(); | ||
| 713 | switch (cmd) { | ||
| 714 | case LPSETTIMEOUT: | ||
| 715 | tc = compat_ptr(arg); | ||
| 716 | if (get_user(par_timeout.tv_sec, &tc->tv_sec) || | ||
| 717 | get_user(par_timeout.tv_usec, &tc->tv_usec)) { | ||
| 718 | ret = -EFAULT; | ||
| 719 | break; | ||
| 720 | } | ||
| 721 | ret = lp_set_timeout(minor, &par_timeout); | ||
| 722 | break; | ||
| 723 | #ifdef LP_STATS | ||
| 724 | case LPGETSTATS: | ||
| 725 | /* FIXME: add an implementation if you set LP_STATS */ | ||
| 726 | ret = -EINVAL; | ||
| 727 | break; | ||
| 728 | #endif | ||
| 729 | default: | ||
| 730 | ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg)); | ||
| 731 | break; | ||
| 732 | } | ||
| 733 | unlock_kernel(); | ||
| 734 | |||
| 735 | return ret; | ||
| 736 | } | ||
| 737 | #endif | ||
| 738 | |||
| 679 | static const struct file_operations lp_fops = { | 739 | static const struct file_operations lp_fops = { |
| 680 | .owner = THIS_MODULE, | 740 | .owner = THIS_MODULE, |
| 681 | .write = lp_write, | 741 | .write = lp_write, |
| 682 | .ioctl = lp_ioctl, | 742 | .unlocked_ioctl = lp_ioctl, |
| 743 | #ifdef CONFIG_COMPAT | ||
| 744 | .compat_ioctl = lp_compat_ioctl, | ||
| 745 | #endif | ||
| 683 | .open = lp_open, | 746 | .open = lp_open, |
| 684 | .release = lp_release, | 747 | .release = lp_release, |
| 685 | #ifdef CONFIG_PARPORT_1284 | 748 | #ifdef CONFIG_PARPORT_1284 |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index ae1f1e699ad7..598763fd207f 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -953,20 +953,6 @@ static int rtc_ioctl(unsigned fd, unsigned cmd, void __user *argp) | |||
| 953 | return -ENOIOCTLCMD; | 953 | return -ENOIOCTLCMD; |
| 954 | } | 954 | } |
| 955 | 955 | ||
| 956 | static int | ||
| 957 | lp_timeout_trans(unsigned int fd, unsigned int cmd, | ||
| 958 | struct compat_timeval __user *tc) | ||
| 959 | { | ||
| 960 | struct timeval __user *tn = compat_alloc_user_space(sizeof(struct timeval)); | ||
| 961 | struct timeval ts; | ||
| 962 | if (get_user(ts.tv_sec, &tc->tv_sec) || | ||
| 963 | get_user(ts.tv_usec, &tc->tv_usec) || | ||
| 964 | put_user(ts.tv_sec, &tn->tv_sec) || | ||
| 965 | put_user(ts.tv_usec, &tn->tv_usec)) | ||
| 966 | return -EFAULT; | ||
| 967 | return sys_ioctl(fd, cmd, (unsigned long)tn); | ||
| 968 | } | ||
| 969 | |||
| 970 | /* on ia32 l_start is on a 32-bit boundary */ | 956 | /* on ia32 l_start is on a 32-bit boundary */ |
| 971 | #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) | 957 | #if defined(CONFIG_IA64) || defined(CONFIG_X86_64) |
| 972 | struct space_resv_32 { | 958 | struct space_resv_32 { |
| @@ -1212,8 +1198,6 @@ COMPATIBLE_IOCTL(PPPIOCGCHAN) | |||
| 1212 | /* PPPOX */ | 1198 | /* PPPOX */ |
| 1213 | COMPATIBLE_IOCTL(PPPOEIOCSFWD) | 1199 | COMPATIBLE_IOCTL(PPPOEIOCSFWD) |
| 1214 | COMPATIBLE_IOCTL(PPPOEIOCDFWD) | 1200 | COMPATIBLE_IOCTL(PPPOEIOCDFWD) |
| 1215 | /* LP */ | ||
| 1216 | COMPATIBLE_IOCTL(LPGETSTATUS) | ||
| 1217 | /* ppdev */ | 1201 | /* ppdev */ |
| 1218 | COMPATIBLE_IOCTL(PPSETMODE) | 1202 | COMPATIBLE_IOCTL(PPSETMODE) |
| 1219 | COMPATIBLE_IOCTL(PPRSTATUS) | 1203 | COMPATIBLE_IOCTL(PPRSTATUS) |
| @@ -1623,19 +1607,6 @@ COMPATIBLE_IOCTL(TIOCSTOP) | |||
| 1623 | /* Usbdevfs */ | 1607 | /* Usbdevfs */ |
| 1624 | COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) | 1608 | COMPATIBLE_IOCTL(USBDEVFS_IOCTL32) |
| 1625 | 1609 | ||
| 1626 | /* parport */ | ||
| 1627 | COMPATIBLE_IOCTL(LPTIME) | ||
| 1628 | COMPATIBLE_IOCTL(LPCHAR) | ||
| 1629 | COMPATIBLE_IOCTL(LPABORTOPEN) | ||
| 1630 | COMPATIBLE_IOCTL(LPCAREFUL) | ||
| 1631 | COMPATIBLE_IOCTL(LPWAIT) | ||
| 1632 | COMPATIBLE_IOCTL(LPSETIRQ) | ||
| 1633 | COMPATIBLE_IOCTL(LPGETSTATUS) | ||
| 1634 | COMPATIBLE_IOCTL(LPGETSTATUS) | ||
| 1635 | COMPATIBLE_IOCTL(LPRESET) | ||
| 1636 | /*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/ | ||
| 1637 | COMPATIBLE_IOCTL(LPGETFLAGS) | ||
| 1638 | |||
| 1639 | /* fat 'r' ioctls. These are handled by fat with ->compat_ioctl, | 1610 | /* fat 'r' ioctls. These are handled by fat with ->compat_ioctl, |
| 1640 | but we don't want warnings on other file systems. So declare | 1611 | but we don't want warnings on other file systems. So declare |
| 1641 | them as compatible here. */ | 1612 | them as compatible here. */ |
| @@ -1734,10 +1705,6 @@ static long do_ioctl_trans(int fd, unsigned int cmd, | |||
| 1734 | return do_video_stillpicture(fd, cmd, argp); | 1705 | return do_video_stillpicture(fd, cmd, argp); |
| 1735 | case VIDEO_SET_SPU_PALETTE: | 1706 | case VIDEO_SET_SPU_PALETTE: |
| 1736 | return do_video_set_spu_palette(fd, cmd, argp); | 1707 | return do_video_set_spu_palette(fd, cmd, argp); |
| 1737 | |||
| 1738 | /* lp */ | ||
| 1739 | case LPSETTIMEOUT: | ||
| 1740 | return lp_timeout_trans(fd, cmd, argp); | ||
| 1741 | } | 1708 | } |
| 1742 | 1709 | ||
| 1743 | /* | 1710 | /* |
