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