diff options
Diffstat (limited to 'fs/ioctl.c')
-rw-r--r-- | fs/ioctl.c | 164 |
1 files changed, 84 insertions, 80 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c index c2a773e8620b..652cacf433ff 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -12,8 +12,8 @@ | |||
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
13 | #include <linux/security.h> | 13 | #include <linux/security.h> |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/uaccess.h> | ||
15 | 16 | ||
16 | #include <asm/uaccess.h> | ||
17 | #include <asm/ioctls.h> | 17 | #include <asm/ioctls.h> |
18 | 18 | ||
19 | static long do_ioctl(struct file *filp, unsigned int cmd, | 19 | static long do_ioctl(struct file *filp, unsigned int cmd, |
@@ -45,31 +45,31 @@ static int file_ioctl(struct file *filp, unsigned int cmd, | |||
45 | { | 45 | { |
46 | int error; | 46 | int error; |
47 | int block; | 47 | int block; |
48 | struct inode * inode = filp->f_path.dentry->d_inode; | 48 | struct inode *inode = filp->f_path.dentry->d_inode; |
49 | int __user *p = (int __user *)arg; | 49 | int __user *p = (int __user *)arg; |
50 | 50 | ||
51 | switch (cmd) { | 51 | switch (cmd) { |
52 | case FIBMAP: | 52 | case FIBMAP: |
53 | { | 53 | { |
54 | struct address_space *mapping = filp->f_mapping; | 54 | struct address_space *mapping = filp->f_mapping; |
55 | int res; | 55 | int res; |
56 | /* do we support this mess? */ | 56 | /* do we support this mess? */ |
57 | if (!mapping->a_ops->bmap) | 57 | if (!mapping->a_ops->bmap) |
58 | return -EINVAL; | 58 | return -EINVAL; |
59 | if (!capable(CAP_SYS_RAWIO)) | 59 | if (!capable(CAP_SYS_RAWIO)) |
60 | return -EPERM; | 60 | return -EPERM; |
61 | if ((error = get_user(block, p)) != 0) | 61 | error = get_user(block, p); |
62 | return error; | 62 | if (error) |
63 | 63 | return error; | |
64 | lock_kernel(); | 64 | lock_kernel(); |
65 | res = mapping->a_ops->bmap(mapping, block); | 65 | res = mapping->a_ops->bmap(mapping, block); |
66 | unlock_kernel(); | 66 | unlock_kernel(); |
67 | return put_user(res, p); | 67 | return put_user(res, p); |
68 | } | 68 | } |
69 | case FIGETBSZ: | 69 | case FIGETBSZ: |
70 | return put_user(inode->i_sb->s_blocksize, p); | 70 | return put_user(inode->i_sb->s_blocksize, p); |
71 | case FIONREAD: | 71 | case FIONREAD: |
72 | return put_user(i_size_read(inode) - filp->f_pos, p); | 72 | return put_user(i_size_read(inode) - filp->f_pos, p); |
73 | } | 73 | } |
74 | 74 | ||
75 | return do_ioctl(filp, cmd, arg); | 75 | return do_ioctl(filp, cmd, arg); |
@@ -82,81 +82,85 @@ static int file_ioctl(struct file *filp, unsigned int cmd, | |||
82 | * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. | 82 | * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. |
83 | * It's just a simple helper for sys_ioctl and compat_sys_ioctl. | 83 | * It's just a simple helper for sys_ioctl and compat_sys_ioctl. |
84 | */ | 84 | */ |
85 | int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) | 85 | int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, |
86 | unsigned long arg) | ||
86 | { | 87 | { |
87 | unsigned int flag; | 88 | unsigned int flag; |
88 | int on, error = 0; | 89 | int on, error = 0; |
89 | 90 | ||
90 | switch (cmd) { | 91 | switch (cmd) { |
91 | case FIOCLEX: | 92 | case FIOCLEX: |
92 | set_close_on_exec(fd, 1); | 93 | set_close_on_exec(fd, 1); |
93 | break; | 94 | break; |
94 | 95 | ||
95 | case FIONCLEX: | 96 | case FIONCLEX: |
96 | set_close_on_exec(fd, 0); | 97 | set_close_on_exec(fd, 0); |
97 | break; | 98 | break; |
98 | 99 | ||
99 | case FIONBIO: | 100 | case FIONBIO: |
100 | if ((error = get_user(on, (int __user *)arg)) != 0) | 101 | error = get_user(on, (int __user *)arg); |
101 | break; | 102 | if (error) |
102 | flag = O_NONBLOCK; | 103 | break; |
104 | flag = O_NONBLOCK; | ||
103 | #ifdef __sparc__ | 105 | #ifdef __sparc__ |
104 | /* SunOS compatibility item. */ | 106 | /* SunOS compatibility item. */ |
105 | if(O_NONBLOCK != O_NDELAY) | 107 | if (O_NONBLOCK != O_NDELAY) |
106 | flag |= O_NDELAY; | 108 | flag |= O_NDELAY; |
107 | #endif | 109 | #endif |
108 | if (on) | 110 | if (on) |
109 | filp->f_flags |= flag; | 111 | filp->f_flags |= flag; |
110 | else | 112 | else |
111 | filp->f_flags &= ~flag; | 113 | filp->f_flags &= ~flag; |
114 | break; | ||
115 | |||
116 | case FIOASYNC: | ||
117 | error = get_user(on, (int __user *)arg); | ||
118 | if (error) | ||
112 | break; | 119 | break; |
113 | 120 | flag = on ? FASYNC : 0; | |
114 | case FIOASYNC: | 121 | |
115 | if ((error = get_user(on, (int __user *)arg)) != 0) | 122 | /* Did FASYNC state change ? */ |
116 | break; | 123 | if ((flag ^ filp->f_flags) & FASYNC) { |
117 | flag = on ? FASYNC : 0; | 124 | if (filp->f_op && filp->f_op->fasync) { |
118 | 125 | lock_kernel(); | |
119 | /* Did FASYNC state change ? */ | 126 | error = filp->f_op->fasync(fd, filp, on); |
120 | if ((flag ^ filp->f_flags) & FASYNC) { | 127 | unlock_kernel(); |
121 | if (filp->f_op && filp->f_op->fasync) { | 128 | } else |
122 | lock_kernel(); | ||
123 | error = filp->f_op->fasync(fd, filp, on); | ||
124 | unlock_kernel(); | ||
125 | } | ||
126 | else error = -ENOTTY; | ||
127 | } | ||
128 | if (error != 0) | ||
129 | break; | ||
130 | |||
131 | if (on) | ||
132 | filp->f_flags |= FASYNC; | ||
133 | else | ||
134 | filp->f_flags &= ~FASYNC; | ||
135 | break; | ||
136 | |||
137 | case FIOQSIZE: | ||
138 | if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || | ||
139 | S_ISREG(filp->f_path.dentry->d_inode->i_mode) || | ||
140 | S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { | ||
141 | loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode); | ||
142 | error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; | ||
143 | } | ||
144 | else | ||
145 | error = -ENOTTY; | 129 | error = -ENOTTY; |
130 | } | ||
131 | if (error != 0) | ||
146 | break; | 132 | break; |
147 | default: | 133 | |
148 | if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) | 134 | if (on) |
149 | error = file_ioctl(filp, cmd, arg); | 135 | filp->f_flags |= FASYNC; |
150 | else | 136 | else |
151 | error = do_ioctl(filp, cmd, arg); | 137 | filp->f_flags &= ~FASYNC; |
152 | break; | 138 | break; |
139 | |||
140 | case FIOQSIZE: | ||
141 | if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || | ||
142 | S_ISREG(filp->f_path.dentry->d_inode->i_mode) || | ||
143 | S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { | ||
144 | loff_t res = | ||
145 | inode_get_bytes(filp->f_path.dentry->d_inode); | ||
146 | error = copy_to_user((loff_t __user *)arg, &res, | ||
147 | sizeof(res)) ? -EFAULT : 0; | ||
148 | } else | ||
149 | error = -ENOTTY; | ||
150 | break; | ||
151 | default: | ||
152 | if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) | ||
153 | error = file_ioctl(filp, cmd, arg); | ||
154 | else | ||
155 | error = do_ioctl(filp, cmd, arg); | ||
156 | break; | ||
153 | } | 157 | } |
154 | return error; | 158 | return error; |
155 | } | 159 | } |
156 | 160 | ||
157 | asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) | 161 | asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) |
158 | { | 162 | { |
159 | struct file * filp; | 163 | struct file *filp; |
160 | int error = -EBADF; | 164 | int error = -EBADF; |
161 | int fput_needed; | 165 | int fput_needed; |
162 | 166 | ||