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 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_path.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_path.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 return put_user(inode->i_sb->s_blocksize, p); 71 case FIONREAD: 72 return put_user(i_size_read(inode) - filp->f_pos, p); 73 } 74 75 return do_ioctl(filp, cmd, arg); 76 } 77 78 /* 79 * When you add any new common ioctls to the switches above and below 80 * please update compat_sys_ioctl() too. 81 * 82 * vfs_ioctl() is not for drivers and not intended to be EXPORT_SYMBOL()'d. 83 * It's just a simple helper for sys_ioctl and compat_sys_ioctl. 84 */ 85 int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) 86 { 87 unsigned int flag; 88 int on, error = 0; 89 90 switch (cmd) { 91 case FIOCLEX: 92 set_close_on_exec(fd, 1); 93 break; 94 95 case FIONCLEX: 96 set_close_on_exec(fd, 0); 97 break; 98 99 case FIONBIO: 100 if ((error = get_user(on, (int __user *)arg)) != 0) 101 break; 102 flag = O_NONBLOCK; 103 #ifdef __sparc__ 104 /* SunOS compatibility item. */ 105 if(O_NONBLOCK != O_NDELAY) 106 flag |= O_NDELAY; 107 #endif 108 if (on) 109 filp->f_flags |= flag; 110 else 111 filp->f_flags &= ~flag; 112 break; 113 114 case FIOASYNC: 115 if ((error = get_user(on, (int __user *)arg)) != 0) 116 break; 117 flag = on ? FASYNC : 0; 118 119 /* Did FASYNC state change ? */ 120 if ((flag ^ filp->f_flags) & FASYNC) { 121 if (filp->f_op && filp->f_op->fasync) { 122 lock_kernel(); 123 error = filp->f_op->fasync(fd, filp, on); 124 unlock_kernel(); 125 } 126 else error = -ENOTTY; 127 } 128 if (error != 0) 129 break; 130 131 if (on) 132 filp->f_flags |= FASYNC; 133 else 134 filp->f_flags &= ~FASYNC; 135 break; 136 137 case FIOQSIZE: 138 if (S_ISDIR(filp->f_path.dentry->d_inode->i_mode) || 139 S_ISREG(filp->f_path.dentry->d_inode->i_mode) || 140 S_ISLNK(filp->f_path.dentry->d_inode->i_mode)) { 141 loff_t res = inode_get_bytes(filp->f_path.dentry->d_inode); 142 error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; 143 } 144 else 145 error = -ENOTTY; 146 break; 147 default: 148 if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) 149 error = file_ioctl(filp, cmd, arg); 150 else 151 error = do_ioctl(filp, cmd, arg); 152 break; 153 } 154 return error; 155 } 156 157 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) 158 { 159 struct file * filp; 160 int error = -EBADF; 161 int fput_needed; 162 163 filp = fget_light(fd, &fput_needed); 164 if (!filp) 165 goto out; 166 167 error = security_file_ioctl(filp, cmd, arg); 168 if (error) 169 goto out_fput; 170 171 error = vfs_ioctl(filp, fd, cmd, arg); 172 out_fput: 173 fput_light(filp, fput_needed); 174 out: 175 return error; 176 } 177 178 /* 179 * Platforms implementing 32 bit compatibility ioctl handlers in 180 * modules need this exported 181 */ 182 #ifdef CONFIG_COMPAT 183 EXPORT_SYMBOL(sys_ioctl); 184 #endif 185