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