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