1/* 2 * linux/fs/ioctl.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7#include <linux/mm.h> 8#include <linux/smp_lock.h> 9#include <linux/file.h> 10 11#include <asm/uaccess.h> 12#include <asm/ioctls.h> 13 14static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) 15{ 16 int error; 17 int block; 18 struct inode * inode = filp->f_dentry->d_inode; 19 20 switch (cmd) { 21 case FIBMAP: 22 { 23 struct address_space *mapping = inode->i_mapping; 24 int res; 25 /* do we support this mess? */ 26 if (!mapping->a_ops->bmap) 27 return -EINVAL; 28 if (!capable(CAP_SYS_RAWIO)) 29 return -EPERM; 30 if ((error = get_user(block, (int *) arg)) != 0) 31 return error; 32 33 res = mapping->a_ops->bmap(mapping, block); 34 return put_user(res, (int *) arg); 35 } 36 case FIGETBSZ: 37 if (inode->i_sb == NULL) 38 return -EBADF; 39 return put_user(inode->i_sb->s_blocksize, (int *) arg); 40 case FIONREAD: 41 return put_user(inode->i_size - filp->f_pos, (int *) arg); 42 } 43 if (filp->f_op && filp->f_op->ioctl) 44 return filp->f_op->ioctl(inode, filp, cmd, arg); 45 return -ENOTTY; 46} 47 48 49asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) 50{ 51 struct file * filp; 52 unsigned int flag; 53 int on, error = -EBADF; 54 55 filp = fget(fd); 56 if (!filp) 57 goto out; 58 error = 0; 59 lock_kernel(); 60 switch (cmd) { 61 case FIOCLEX: 62 set_close_on_exec(fd, 1); 63 break; 64 65 case FIONCLEX: 66 set_close_on_exec(fd, 0); 67 break; 68 69 case FIONBIO: 70 if ((error = get_user(on, (int *)arg)) != 0) 71 break; 72 flag = O_NONBLOCK; 73#ifdef __sparc__ 74 /* SunOS compatibility item. */ 75 if(O_NONBLOCK != O_NDELAY) 76 flag |= O_NDELAY; 77#endif 78 if (on) 79 filp->f_flags |= flag; 80 else 81 filp->f_flags &= ~flag; 82 break; 83 84 case FIOASYNC: 85 if ((error = get_user(on, (int *)arg)) != 0) 86 break; 87 flag = on ? FASYNC : 0; 88 89 /* Did FASYNC state change ? */ 90 if ((flag ^ filp->f_flags) & FASYNC) { 91 if (filp->f_op && filp->f_op->fasync) 92 error = filp->f_op->fasync(fd, filp, on); 93 else error = -ENOTTY; 94 } 95 if (error != 0) 96 break; 97 98 if (on) 99 filp->f_flags |= FASYNC; 100 else 101 filp->f_flags &= ~FASYNC; 102 break; 103 104 default: 105 error = -ENOTTY; 106 if (S_ISREG(filp->f_dentry->d_inode->i_mode)) 107 error = file_ioctl(filp, cmd, arg); 108 else if (filp->f_op && filp->f_op->ioctl) 109 error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); 110 } 111 unlock_kernel(); 112 fput(filp); 113 114out: 115 return error; 116} 117