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