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