aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ioctl.c')
-rw-r--r--fs/ioctl.c129
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
55static 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
55static int file_ioctl(struct file *filp, unsigned int cmd, 74static 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
92static 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
113static 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,
97int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, 150int 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: