diff options
Diffstat (limited to 'fs/ioctl.c')
-rw-r--r-- | fs/ioctl.c | 129 |
1 files changed, 75 insertions, 54 deletions
diff --git a/fs/ioctl.c b/fs/ioctl.c index e6500cd12258..683002fefa55 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -52,32 +52,34 @@ long vfs_ioctl(struct file *filp, unsigned int cmd, | |||
52 | return error; | 52 | return error; |
53 | } | 53 | } |
54 | 54 | ||
55 | static int ioctl_fibmap(struct file *filp, int __user *p) | ||
56 | { | ||
57 | struct address_space *mapping = filp->f_mapping; | ||
58 | int res, block; | ||
59 | |||
60 | /* do we support this mess? */ | ||
61 | if (!mapping->a_ops->bmap) | ||
62 | return -EINVAL; | ||
63 | if (!capable(CAP_SYS_RAWIO)) | ||
64 | return -EPERM; | ||
65 | res = get_user(block, p); | ||
66 | if (res) | ||
67 | return res; | ||
68 | lock_kernel(); | ||
69 | res = mapping->a_ops->bmap(mapping, block); | ||
70 | unlock_kernel(); | ||
71 | return put_user(res, p); | ||
72 | } | ||
73 | |||
55 | static int file_ioctl(struct file *filp, unsigned int cmd, | 74 | static int file_ioctl(struct file *filp, unsigned int cmd, |
56 | unsigned long arg) | 75 | unsigned long arg) |
57 | { | 76 | { |
58 | int error; | ||
59 | int block; | ||
60 | struct inode *inode = filp->f_path.dentry->d_inode; | 77 | struct inode *inode = filp->f_path.dentry->d_inode; |
61 | int __user *p = (int __user *)arg; | 78 | int __user *p = (int __user *)arg; |
62 | 79 | ||
63 | switch (cmd) { | 80 | switch (cmd) { |
64 | case FIBMAP: | 81 | case FIBMAP: |
65 | { | 82 | return ioctl_fibmap(filp, p); |
66 | struct address_space *mapping = filp->f_mapping; | ||
67 | int res; | ||
68 | /* do we support this mess? */ | ||
69 | if (!mapping->a_ops->bmap) | ||
70 | return -EINVAL; | ||
71 | if (!capable(CAP_SYS_RAWIO)) | ||
72 | return -EPERM; | ||
73 | error = get_user(block, p); | ||
74 | if (error) | ||
75 | return error; | ||
76 | lock_kernel(); | ||
77 | res = mapping->a_ops->bmap(mapping, block); | ||
78 | unlock_kernel(); | ||
79 | return put_user(res, p); | ||
80 | } | ||
81 | case FIGETBSZ: | 83 | case FIGETBSZ: |
82 | return put_user(inode->i_sb->s_blocksize, p); | 84 | return put_user(inode->i_sb->s_blocksize, p); |
83 | case FIONREAD: | 85 | case FIONREAD: |
@@ -87,6 +89,57 @@ static int file_ioctl(struct file *filp, unsigned int cmd, | |||
87 | return vfs_ioctl(filp, cmd, arg); | 89 | return vfs_ioctl(filp, cmd, arg); |
88 | } | 90 | } |
89 | 91 | ||
92 | static int ioctl_fionbio(struct file *filp, int __user *argp) | ||
93 | { | ||
94 | unsigned int flag; | ||
95 | int on, error; | ||
96 | |||
97 | error = get_user(on, argp); | ||
98 | if (error) | ||
99 | return error; | ||
100 | flag = O_NONBLOCK; | ||
101 | #ifdef __sparc__ | ||
102 | /* SunOS compatibility item. */ | ||
103 | if (O_NONBLOCK != O_NDELAY) | ||
104 | flag |= O_NDELAY; | ||
105 | #endif | ||
106 | if (on) | ||
107 | filp->f_flags |= flag; | ||
108 | else | ||
109 | filp->f_flags &= ~flag; | ||
110 | return error; | ||
111 | } | ||
112 | |||
113 | static int ioctl_fioasync(unsigned int fd, struct file *filp, | ||
114 | int __user *argp) | ||
115 | { | ||
116 | unsigned int flag; | ||
117 | int on, error; | ||
118 | |||
119 | error = get_user(on, argp); | ||
120 | if (error) | ||
121 | return error; | ||
122 | flag = on ? FASYNC : 0; | ||
123 | |||
124 | /* Did FASYNC state change ? */ | ||
125 | if ((flag ^ filp->f_flags) & FASYNC) { | ||
126 | if (filp->f_op && filp->f_op->fasync) { | ||
127 | lock_kernel(); | ||
128 | error = filp->f_op->fasync(fd, filp, on); | ||
129 | unlock_kernel(); | ||
130 | } else | ||
131 | error = -ENOTTY; | ||
132 | } | ||
133 | if (error) | ||
134 | return error; | ||
135 | |||
136 | if (on) | ||
137 | filp->f_flags |= FASYNC; | ||
138 | else | ||
139 | filp->f_flags &= ~FASYNC; | ||
140 | return error; | ||
141 | } | ||
142 | |||
90 | /* | 143 | /* |
91 | * When you add any new common ioctls to the switches above and below | 144 | * When you add any new common ioctls to the switches above and below |
92 | * please update compat_sys_ioctl() too. | 145 | * please update compat_sys_ioctl() too. |
@@ -97,8 +150,8 @@ static int file_ioctl(struct file *filp, unsigned int cmd, | |||
97 | int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | 150 | int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, |
98 | unsigned long arg) | 151 | unsigned long arg) |
99 | { | 152 | { |
100 | unsigned int flag; | 153 | int error = 0; |
101 | int on, error = 0; | 154 | int __user *argp = (int __user *)arg; |
102 | 155 | ||
103 | switch (cmd) { | 156 | switch (cmd) { |
104 | case FIOCLEX: | 157 | case FIOCLEX: |
@@ -110,43 +163,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | |||
110 | break; | 163 | break; |
111 | 164 | ||
112 | case FIONBIO: | 165 | case FIONBIO: |
113 | error = get_user(on, (int __user *)arg); | 166 | error = ioctl_fionbio(filp, argp); |
114 | if (error) | ||
115 | break; | ||
116 | flag = O_NONBLOCK; | ||
117 | #ifdef __sparc__ | ||
118 | /* SunOS compatibility item. */ | ||
119 | if (O_NONBLOCK != O_NDELAY) | ||
120 | flag |= O_NDELAY; | ||
121 | #endif | ||
122 | if (on) | ||
123 | filp->f_flags |= flag; | ||
124 | else | ||
125 | filp->f_flags &= ~flag; | ||
126 | break; | 167 | break; |
127 | 168 | ||
128 | case FIOASYNC: | 169 | case FIOASYNC: |
129 | error = get_user(on, (int __user *)arg); | 170 | error = ioctl_fioasync(fd, filp, argp); |
130 | if (error) | ||
131 | break; | ||
132 | flag = on ? FASYNC : 0; | ||
133 | |||
134 | /* Did FASYNC state change ? */ | ||
135 | if ((flag ^ filp->f_flags) & FASYNC) { | ||
136 | if (filp->f_op && filp->f_op->fasync) { | ||
137 | lock_kernel(); | ||
138 | error = filp->f_op->fasync(fd, filp, on); | ||
139 | unlock_kernel(); | ||
140 | } else | ||
141 | error = -ENOTTY; | ||
142 | } | ||
143 | if (error != 0) | ||
144 | break; | ||
145 | |||
146 | if (on) | ||
147 | filp->f_flags |= FASYNC; | ||
148 | else | ||
149 | filp->f_flags &= ~FASYNC; | ||
150 | break; | 171 | break; |
151 | 172 | ||
152 | case FIOQSIZE: | 173 | case FIOQSIZE: |