Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 
 16 #include <asm/uaccess.h>
 17 #include <asm/ioctls.h>
 18 
 19 static long do_ioctl(struct file *filp, unsigned int cmd,
 20                 unsigned long arg)
 21 {
 22         int error = -ENOTTY;
 23 
 24         if (!filp->f_op)
 25                 goto out;
 26 
 27         if (filp->f_op->unlocked_ioctl) {
 28                 error = filp->f_op->unlocked_ioctl(filp, cmd, arg);
 29                 if (error == -ENOIOCTLCMD)
 30                         error = -EINVAL;
 31                 goto out;
 32         } else if (filp->f_op->ioctl) {
 33                 lock_kernel();
 34                 error = filp->f_op->ioctl(filp->f_dentry->d_inode,
 35                                           filp, cmd, arg);
 36                 unlock_kernel();
 37         }
 38 
 39  out:
 40         return error;
 41 }
 42 
 43 static int file_ioctl(struct file *filp, unsigned int cmd,
 44                 unsigned long arg)
 45 {
 46         int error;
 47         int block;
 48         struct inode * inode = filp->f_dentry->d_inode;
 49         int __user *p = (int __user *)arg;
 50 
 51         switch (cmd) {
 52                 case FIBMAP:
 53                 {
 54                         struct address_space *mapping = filp->f_mapping;
 55                         int res;
 56                         /* do we support this mess? */
 57                         if (!mapping->a_ops->bmap)
 58                                 return -EINVAL;
 59                         if (!capable(CAP_SYS_RAWIO))
 60                                 return -EPERM;
 61                         if ((error = get_user(block, p)) != 0)
 62                                 return error;
 63 
 64                         lock_kernel();
 65                         res = mapping->a_ops->bmap(mapping, block);
 66                         unlock_kernel();
 67                         return put_user(res, p);
 68                 }
 69                 case FIGETBSZ:
 70                         if (inode->i_sb == NULL)
 71                                 return -EBADF;
 72                         return put_user(inode->i_sb->s_blocksize, p);
 73                 case FIONREAD:
 74                         return put_user(i_size_read(inode) - filp->f_pos, p);
 75         }
 76 
 77         return do_ioctl(filp, cmd, arg);
 78 }
 79 
 80 /*
 81  * When you add any new common ioctls to the switches above and below
 82  * please update compat_sys_ioctl() too.
 83  *
 84  * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d.
 85  * It's just a simple helper for sys_ioctl and compat_sys_ioctl.
 86  */
 87 int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg)
 88 {
 89         unsigned int flag;
 90         int on, error = 0;
 91 
 92         switch (cmd) {
 93                 case FIOCLEX:
 94                         set_close_on_exec(fd, 1);
 95                         break;
 96 
 97                 case FIONCLEX:
 98                         set_close_on_exec(fd, 0);
 99                         break;
100 
101                 case FIONBIO:
102                         if ((error = get_user(on, (int __user *)arg)) != 0)
103                                 break;
104                         flag = O_NONBLOCK;
105 #ifdef __sparc__
106                         /* SunOS compatibility item. */
107                         if(O_NONBLOCK != O_NDELAY)
108                                 flag |= O_NDELAY;
109 #endif
110                         if (on)
111                                 filp->f_flags |= flag;
112                         else
113                                 filp->f_flags &= ~flag;
114                         break;
115 
116                 case FIOASYNC:
117                         if ((error = get_user(on, (int __user *)arg)) != 0)
118                                 break;
119                         flag = on ? FASYNC : 0;
120 
121                         /* Did FASYNC state change ? */
122                         if ((flag ^ filp->f_flags) & FASYNC) {
123                                 if (filp->f_op && filp->f_op->fasync) {
124                                         lock_kernel();
125                                         error = filp->f_op->fasync(fd, filp, on);
126                                         unlock_kernel();
127                                 }
128                                 else error = -ENOTTY;
129                         }
130                         if (error != 0)
131                                 break;
132 
133                         if (on)
134                                 filp->f_flags |= FASYNC;
135                         else
136                                 filp->f_flags &= ~FASYNC;
137                         break;
138 
139                 case FIOQSIZE:
140                         if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
141                             S_ISREG(filp->f_dentry->d_inode->i_mode) ||
142                             S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
143                                 loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
144                                 error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0;
145                         }
146                         else
147                                 error = -ENOTTY;
148                         break;
149                 default:
150                         if (S_ISREG(filp->f_dentry->d_inode->i_mode))
151                                 error = file_ioctl(filp, cmd, arg);
152                         else
153                                 error = do_ioctl(filp, cmd, arg);
154                         break;
155         }
156         return error;
157 }
158 
159 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
160 {
161         struct file * filp;
162         int error = -EBADF;
163         int fput_needed;
164 
165         filp = fget_light(fd, &fput_needed);
166         if (!filp)
167                 goto out;
168 
169         error = security_file_ioctl(filp, cmd, arg);
170         if (error)
171                 goto out_fput;
172 
173         error = vfs_ioctl(filp, fd, cmd, arg);
174  out_fput:
175         fput_light(filp, fput_needed);
176  out:
177         return error;
178 }
179 
180 /*
181  * Platforms implementing 32 bit compatibility ioctl handlers in
182  * modules need this exported
183  */
184 #ifdef CONFIG_COMPAT
185 EXPORT_SYMBOL(sys_ioctl);
186 #endif
187 
  This page was automatically generated by the LXR engine.