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