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