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