kernel.org linux-2.6.10
[linux-2.6.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 int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
20 {
21         int error;
22         int block;
23         struct inode * inode = filp->f_dentry->d_inode;
24         int __user *p = (int __user *)arg;
25
26         switch (cmd) {
27                 case FIBMAP:
28                 {
29                         struct address_space *mapping = filp->f_mapping;
30                         int res;
31                         /* do we support this mess? */
32                         if (!mapping->a_ops->bmap)
33                                 return -EINVAL;
34                         if (!capable(CAP_SYS_RAWIO))
35                                 return -EPERM;
36                         if ((error = get_user(block, p)) != 0)
37                                 return error;
38
39                         res = mapping->a_ops->bmap(mapping, block);
40                         return put_user(res, p);
41                 }
42                 case FIGETBSZ:
43                         if (inode->i_sb == NULL)
44                                 return -EBADF;
45                         return put_user(inode->i_sb->s_blocksize, p);
46                 case FIONREAD:
47                         return put_user(i_size_read(inode) - filp->f_pos, p);
48         }
49         if (filp->f_op && filp->f_op->ioctl)
50                 return filp->f_op->ioctl(inode, filp, cmd, arg);
51         return -ENOTTY;
52 }
53
54
55 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
56 {       
57         struct file * filp;
58         unsigned int flag;
59         int on, error = -EBADF;
60
61         filp = fget(fd);
62         if (!filp)
63                 goto out;
64
65         error = security_file_ioctl(filp, cmd, arg);
66         if (error) {
67                 fput(filp);
68                 goto out;
69         }
70
71         lock_kernel();
72         switch (cmd) {
73                 case FIOCLEX:
74                         set_close_on_exec(fd, 1);
75                         break;
76
77                 case FIONCLEX:
78                         set_close_on_exec(fd, 0);
79                         break;
80
81                 case FIONBIO:
82                         if ((error = get_user(on, (int __user *)arg)) != 0)
83                                 break;
84                         flag = O_NONBLOCK;
85 #ifdef __sparc__
86                         /* SunOS compatibility item. */
87                         if(O_NONBLOCK != O_NDELAY)
88                                 flag |= O_NDELAY;
89 #endif
90                         if (on)
91                                 filp->f_flags |= flag;
92                         else
93                                 filp->f_flags &= ~flag;
94                         break;
95
96                 case FIOASYNC:
97                         if ((error = get_user(on, (int __user *)arg)) != 0)
98                                 break;
99                         flag = on ? FASYNC : 0;
100
101                         /* Did FASYNC state change ? */
102                         if ((flag ^ filp->f_flags) & FASYNC) {
103                                 if (filp->f_op && filp->f_op->fasync)
104                                         error = filp->f_op->fasync(fd, filp, on);
105                                 else error = -ENOTTY;
106                         }
107                         if (error != 0)
108                                 break;
109
110                         if (on)
111                                 filp->f_flags |= FASYNC;
112                         else
113                                 filp->f_flags &= ~FASYNC;
114                         break;
115
116                 case FIOQSIZE:
117                         if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
118                             S_ISREG(filp->f_dentry->d_inode->i_mode) ||
119                             S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
120                                 loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
121                                 error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
122                         }
123                         else
124                                 error = -ENOTTY;
125                         break;
126                 default:
127                         error = -ENOTTY;
128                         if (S_ISREG(filp->f_dentry->d_inode->i_mode))
129                                 error = file_ioctl(filp, cmd, arg);
130                         else if (filp->f_op && filp->f_op->ioctl)
131                                 error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
132         }
133         unlock_kernel();
134         fput(filp);
135
136 out:
137         return error;
138 }
139
140 /*
141  * Platforms implementing 32 bit compatibility ioctl handlers in
142  * modules need this exported
143  */
144 #ifdef CONFIG_COMPAT
145 EXPORT_SYMBOL(sys_ioctl);
146 #endif