upgrade to vserver 1.9.3.17
[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 #include <linux/proc_fs.h>
16 #include <linux/vserver/inode.h>
17 #include <linux/vserver/xid.h>
18 #include <linux/module.h>
19
20 #include <asm/uaccess.h>
21 #include <asm/ioctls.h>
22
23 #ifdef  CONFIG_VSERVER_LEGACY
24 extern int vx_proc_ioctl(struct inode *, struct file *,
25         unsigned int, unsigned long);
26 #endif
27
28 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
29 {
30         int error;
31         int block;
32         struct inode * inode = filp->f_dentry->d_inode;
33         int __user *p = (int __user *)arg;
34
35         switch (cmd) {
36                 case FIBMAP:
37                 {
38                         struct address_space *mapping = filp->f_mapping;
39                         int res;
40                         /* do we support this mess? */
41                         if (!mapping->a_ops->bmap)
42                                 return -EINVAL;
43                         if (!capable(CAP_SYS_RAWIO))
44                                 return -EPERM;
45                         if ((error = get_user(block, p)) != 0)
46                                 return error;
47
48                         res = mapping->a_ops->bmap(mapping, block);
49                         return put_user(res, p);
50                 }
51                 case FIGETBSZ:
52                         if (inode->i_sb == NULL)
53                                 return -EBADF;
54                         return put_user(inode->i_sb->s_blocksize, p);
55                 case FIONREAD:
56                         return put_user(i_size_read(inode) - filp->f_pos, p);
57         }
58         if (filp->f_op && filp->f_op->ioctl)
59                 return filp->f_op->ioctl(inode, filp, cmd, arg);
60         return -ENOTTY;
61 }
62
63
64 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
65 {       
66         struct file * filp;
67         unsigned int flag;
68         int on, error = -EBADF;
69
70         filp = fget(fd);
71         if (!filp)
72                 goto out;
73
74         error = security_file_ioctl(filp, cmd, arg);
75         if (error) {
76                 fput(filp);
77                 goto out;
78         }
79
80         lock_kernel();
81         switch (cmd) {
82                 case FIOCLEX:
83                         set_close_on_exec(fd, 1);
84                         break;
85
86                 case FIONCLEX:
87                         set_close_on_exec(fd, 0);
88                         break;
89
90                 case FIONBIO:
91                         if ((error = get_user(on, (int __user *)arg)) != 0)
92                                 break;
93                         flag = O_NONBLOCK;
94 #ifdef __sparc__
95                         /* SunOS compatibility item. */
96                         if(O_NONBLOCK != O_NDELAY)
97                                 flag |= O_NDELAY;
98 #endif
99                         if (on)
100                                 filp->f_flags |= flag;
101                         else
102                                 filp->f_flags &= ~flag;
103                         break;
104
105                 case FIOASYNC:
106                         if ((error = get_user(on, (int __user *)arg)) != 0)
107                                 break;
108                         flag = on ? FASYNC : 0;
109
110                         /* Did FASYNC state change ? */
111                         if ((flag ^ filp->f_flags) & FASYNC) {
112                                 if (filp->f_op && filp->f_op->fasync)
113                                         error = filp->f_op->fasync(fd, filp, on);
114                                 else error = -ENOTTY;
115                         }
116                         if (error != 0)
117                                 break;
118
119                         if (on)
120                                 filp->f_flags |= FASYNC;
121                         else
122                                 filp->f_flags &= ~FASYNC;
123                         break;
124
125                 case FIOQSIZE:
126                         if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
127                             S_ISREG(filp->f_dentry->d_inode->i_mode) ||
128                             S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
129                                 loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
130                                 error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
131                         }
132                         else
133                                 error = -ENOTTY;
134                         break;
135 #ifdef  CONFIG_VSERVER_LEGACY
136 #ifndef CONFIG_INOXID_NONE
137                 case FIOC_GETXID: {
138                         struct inode *inode = filp->f_dentry->d_inode;
139
140                         /* fixme: if stealth, return -ENOTTY */
141                         error = -EPERM;
142                         if (capable(CAP_CONTEXT))
143                                 error = put_user(inode->i_xid, (int *) arg);
144                         break;
145                 }
146                 case FIOC_SETXID: {
147                         struct inode *inode = filp->f_dentry->d_inode;
148                         int xid;
149
150                         /* fixme: if stealth, return -ENOTTY */
151                         error = -EPERM;
152                         if (!capable(CAP_CONTEXT))
153                                 break;
154                         error = -EROFS;
155                         if (IS_RDONLY(inode))
156                                 break;
157                         error = -ENOSYS;
158                         if (!(inode->i_sb->s_flags & MS_TAGXID))
159                                 break;
160                         error = -EFAULT;
161                         if (get_user(xid, (int *) arg))
162                                 break;
163                         error = 0;
164                         inode->i_xid = (xid & 0xFFFF);
165                         inode->i_ctime = CURRENT_TIME;
166                         mark_inode_dirty(inode);
167                         break;
168                 }
169 #endif
170                 case FIOC_GETXFLG:
171                 case FIOC_SETXFLG:
172                         error = -ENOTTY;
173                         if (filp->f_dentry->d_inode->i_sb->s_magic == PROC_SUPER_MAGIC)
174                                 error = vx_proc_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
175                         break;
176 #endif
177                 default:
178                         error = -ENOTTY;
179                         if (S_ISREG(filp->f_dentry->d_inode->i_mode))
180                                 error = file_ioctl(filp, cmd, arg);
181                         else if (filp->f_op && filp->f_op->ioctl)
182                                 error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
183         }
184         unlock_kernel();
185         fput(filp);
186
187 out:
188         return error;
189 }
190
191 /*
192  * Platforms implementing 32 bit compatibility ioctl handlers in
193  * modules need this exported
194  */
195 #ifdef CONFIG_COMPAT
196 EXPORT_SYMBOL(sys_ioctl);
197 #endif