- patches.fixes/patch-2.6.11-rc1: 2.6.11-rc1.
[linux-flexiantxendom0-3.2.10.git] / fs / ioctl.c
1 /*
2  *  linux/fs/ioctl.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6
7 #include <linux/config.h>
8 #include <linux/syscalls.h>
9 #include <linux/mm.h>
10 #include <linux/smp_lock.h>
11 #include <linux/file.h>
12 #include <linux/fs.h>
13 #include <linux/security.h>
14 #include <linux/module.h>
15
16 #include <asm/uaccess.h>
17 #include <asm/ioctls.h>
18
19 static long do_ioctl(struct file *filp, unsigned int cmd,
20                 unsigned long arg)
21 {
22         int error = -ENOTTY;
23
24         if (!filp->f_op)
25                 goto out;
26
27         if (filp->f_op->unlocked_ioctl) {
28                 error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
29                 if (error == -ENOIOCTLCMD)
30                         error = -EINVAL;
31                 goto out;
32         } else if (filp->f_op->ioctl) {
33                 lock_kernel();
34                 error = filp->f_op->ioctl(filp->f_dentry->d_inode,
35                                           filp, cmd, arg);
36                 unlock_kernel();
37         }
38
39  out:
40         return error;
41 }
42
43 static int file_ioctl(struct file *filp, unsigned int cmd,
44                 unsigned long arg)
45 {
46         int error;
47         int block;
48         struct inode * inode = filp->f_dentry->d_inode;
49         int __user *p = (int __user *)arg;
50
51         switch (cmd) {
52                 case FIBMAP:
53                 {
54                         struct address_space *mapping = filp->f_mapping;
55                         int res;
56                         /* do we support this mess? */
57                         if (!mapping->a_ops->bmap)
58                                 return -EINVAL;
59                         if (!capable(CAP_SYS_RAWIO))
60                                 return -EPERM;
61                         if ((error = get_user(block, p)) != 0)
62                                 return error;
63
64                         lock_kernel();
65                         res = mapping->a_ops->bmap(mapping, block);
66                         unlock_kernel();
67                         return put_user(res, p);
68                 }
69                 case FIGETBSZ:
70                         if (inode->i_sb == NULL)
71                                 return -EBADF;
72                         return put_user(inode->i_sb->s_blocksize, p);
73                 case FIONREAD:
74                         return put_user(i_size_read(inode) - filp->f_pos, p);
75         }
76
77         return do_ioctl(filp, cmd, arg);
78 }
79
80
81 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
82 {
83         struct file * filp;
84         unsigned int flag;
85         int on, error = -EBADF;
86         int fput_needed;
87
88         filp = fget_light(fd, &fput_needed);
89         if (!filp)
90                 goto out;
91
92         error = security_file_ioctl(filp, cmd, arg);
93         if (error)
94                 goto out_fput;
95
96         switch (cmd) {
97                 case FIOCLEX:
98                         set_close_on_exec(fd, 1);
99                         break;
100
101                 case FIONCLEX:
102                         set_close_on_exec(fd, 0);
103                         break;
104
105                 case FIONBIO:
106                         if ((error = get_user(on, (int __user *)arg)) != 0)
107                                 break;
108                         flag = O_NONBLOCK;
109 #ifdef __sparc__
110                         /* SunOS compatibility item. */
111                         if(O_NONBLOCK != O_NDELAY)
112                                 flag |= O_NDELAY;
113 #endif
114                         if (on)
115                                 filp->f_flags |= flag;
116                         else
117                                 filp->f_flags &= ~flag;
118                         break;
119
120                 case FIOASYNC:
121                         if ((error = get_user(on, (int __user *)arg)) != 0)
122                                 break;
123                         flag = on ? FASYNC : 0;
124
125                         /* Did FASYNC state change ? */
126                         if ((flag ^ filp->f_flags) & FASYNC) {
127                                 if (filp->f_op && filp->f_op->fasync) {
128                                         lock_kernel();
129                                         error = filp->f_op->fasync(fd, filp, on);
130                                         unlock_kernel();
131                                 }
132                                 else error = -ENOTTY;
133                         }
134                         if (error != 0)
135                                 break;
136
137                         if (on)
138                                 filp->f_flags |= FASYNC;
139                         else
140                                 filp->f_flags &= ~FASYNC;
141                         break;
142
143                 case FIOQSIZE:
144                         if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
145                             S_ISREG(filp->f_dentry->d_inode->i_mode) ||
146                             S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
147                                 loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
148                                 error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
149                         }
150                         else
151                                 error = -ENOTTY;
152                         break;
153                 default:
154                         if (S_ISREG(filp->f_dentry->d_inode->i_mode))
155                                 error = file_ioctl(filp, cmd, arg);
156                         else
157                                 error = do_ioctl(filp, cmd, arg);
158                         break;
159         }
160  out_fput:
161         fput_light(filp, fput_needed);
162  out:
163         return error;
164 }
165
166 /*
167  * Platforms implementing 32 bit compatibility ioctl handlers in
168  * modules need this exported
169  */
170 #ifdef CONFIG_COMPAT
171 EXPORT_SYMBOL(sys_ioctl);
172 #endif