Signed-off-by: Andrew Morton --- 25-akpm/fs/ioctl.c | 182 ++++++++++++++++++++++++++--------------------------- 1 files changed, 92 insertions(+), 90 deletions(-) diff -puN fs/ioctl.c~ioctl-cleanup fs/ioctl.c --- 25/fs/ioctl.c~ioctl-cleanup 2004-12-09 20:55:23.521523040 -0800 +++ 25-akpm/fs/ioctl.c 2004-12-09 21:10:47.000132952 -0800 @@ -16,46 +16,12 @@ #include #include -static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) -{ - int error; - int block; - struct inode * inode = filp->f_dentry->d_inode; - int __user *p = (int __user *)arg; - - switch (cmd) { - case FIBMAP: - { - struct address_space *mapping = filp->f_mapping; - int res; - /* do we support this mess? */ - if (!mapping->a_ops->bmap) - return -EINVAL; - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; - if ((error = get_user(block, p)) != 0) - return error; - - res = mapping->a_ops->bmap(mapping, block); - return put_user(res, p); - } - case FIGETBSZ: - if (inode->i_sb == NULL) - return -EBADF; - return put_user(inode->i_sb->s_blocksize, p); - case FIONREAD: - return put_user(i_size_read(inode) - filp->f_pos, p); - } - if (filp->f_op && filp->f_op->ioctl) - return filp->f_op->ioctl(inode, filp, cmd, arg); - return -ENOTTY; -} - - asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) { - struct file * filp; + struct inode *inode; + struct file *filp; unsigned int flag; + int __user *p = (int __user *)arg; int on, error = -EBADF; filp = fget(fd); @@ -68,71 +34,107 @@ asmlinkage long sys_ioctl(unsigned int f goto out; } + inode = filp->f_dentry->d_inode; lock_kernel(); switch (cmd) { - case FIOCLEX: - set_close_on_exec(fd, 1); - break; - - case FIONCLEX: - set_close_on_exec(fd, 0); - break; - - case FIONBIO: - if ((error = get_user(on, (int __user *)arg)) != 0) - break; - flag = O_NONBLOCK; + case FIOCLEX: + set_close_on_exec(fd, 1); + goto done; + case FIONCLEX: + set_close_on_exec(fd, 0); + goto done; + case FIONBIO: + if ((error = get_user(on, (int __user *)arg)) != 0) + goto done; + flag = O_NONBLOCK; #ifdef __sparc__ - /* SunOS compatibility item. */ - if(O_NONBLOCK != O_NDELAY) - flag |= O_NDELAY; + /* SunOS compatibility item. */ + if(O_NONBLOCK != O_NDELAY) + flag |= O_NDELAY; #endif - if (on) - filp->f_flags |= flag; + if (on) + filp->f_flags |= flag; + else + filp->f_flags &= ~flag; + goto done; + case FIOASYNC: + if ((error = get_user(on, (int __user *)arg)) != 0) + goto done; + flag = on ? FASYNC : 0; + + /* Did FASYNC state change ? */ + if ((flag ^ filp->f_flags) & FASYNC) { + if (filp->f_op && filp->f_op->fasync) + error = filp->f_op->fasync(fd, filp, on); else - filp->f_flags &= ~flag; - break; - - case FIOASYNC: - if ((error = get_user(on, (int __user *)arg)) != 0) - break; - flag = on ? FASYNC : 0; - - /* Did FASYNC state change ? */ - if ((flag ^ filp->f_flags) & FASYNC) { - if (filp->f_op && filp->f_op->fasync) - error = filp->f_op->fasync(fd, filp, on); - else error = -ENOTTY; - } - if (error != 0) - break; + error = -ENOTTY; + } + if (error != 0) + goto done; - if (on) - filp->f_flags |= FASYNC; - else - filp->f_flags &= ~FASYNC; - break; + if (on) + filp->f_flags |= FASYNC; + else + filp->f_flags &= ~FASYNC; + goto done; + case FIOQSIZE: + error = -ENOTTY; + if (S_ISDIR(inode->i_mode) || S_ISREG(inode->i_mode) || + S_ISLNK(inode->i_mode)) { + loff_t res = inode_get_bytes(inode); + error = put_user(res, (loff_t __user *)arg); + } + goto done; + case FIBMAP: + { + struct address_space *mapping = filp->f_mapping; + int block; + int res; - case FIOQSIZE: - if (S_ISDIR(filp->f_dentry->d_inode->i_mode) || - S_ISREG(filp->f_dentry->d_inode->i_mode) || - S_ISLNK(filp->f_dentry->d_inode->i_mode)) { - loff_t res = inode_get_bytes(filp->f_dentry->d_inode); - error = copy_to_user((loff_t __user *)arg, &res, sizeof(res)) ? -EFAULT : 0; - } - else + if (!S_ISREG(inode->i_mode)) { error = -ENOTTY; - break; - default: + goto done; + } + /* do we support this mess? */ + if (!mapping->a_ops->bmap) { + error = -EINVAL; + goto done; + } + if (!capable(CAP_SYS_RAWIO)) { + error = -EPERM; + goto done; + } + if ((error = get_user(block, p))) + goto done; + + res = mapping->a_ops->bmap(mapping, block); + error = put_user(res, p); + goto done; + } + case FIGETBSZ: + if (!S_ISREG(inode->i_mode)) { + error = -ENOTTY; + goto done; + } + error = -EBADF; + if (inode->i_sb) + error = put_user(inode->i_sb->s_blocksize, p); + goto done; + case FIONREAD: + if (!S_ISREG(inode->i_mode)) { error = -ENOTTY; - if (S_ISREG(filp->f_dentry->d_inode->i_mode)) - error = file_ioctl(filp, cmd, arg); - else if (filp->f_op && filp->f_op->ioctl) - error = filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg); + goto done; + } + error = put_user(i_size_read(inode) - filp->f_pos, p); + goto done; } + + error = -ENOTTY; + if (filp->f_op && filp->f_op->ioctl) + error = filp->f_op->ioctl(inode, filp, cmd, arg); +done: unlock_kernel(); fput(filp); - out: return error; } _