X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=fs%2Fioctl.c;h=7db32b3382d3a66452388ad9e9023216a1855ab3;hb=1ef708ea449e5eab2780020ec79485db80937833;hp=e6500cd122584e830f66d8af209ea817004f68dc;hpb=deb21db7788b97a2bccdefe605433ef97f482689;p=linux-2.6 diff --git a/fs/ioctl.c b/fs/ioctl.c index e6500cd122..7db32b3382 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -18,18 +18,18 @@ /** * vfs_ioctl - call filesystem specific ioctl methods - * @filp: [in] open file to invoke ioctl method on - * @cmd: [in] ioctl command to execute - * @arg: [in/out] command-specific argument for ioctl + * @filp: open file to invoke ioctl method on + * @cmd: ioctl command to execute + * @arg: command-specific argument for ioctl * * Invokes filesystem specific ->unlocked_ioctl, if one exists; otherwise - * invokes * filesystem specific ->ioctl method. If neither method exists, + * invokes filesystem specific ->ioctl method. If neither method exists, * returns -ENOTTY. * * Returns 0 on success, -errno on error. */ -long vfs_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) +static long vfs_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg) { int error = -ENOTTY; @@ -52,32 +52,34 @@ long vfs_ioctl(struct file *filp, unsigned int cmd, return error; } +static int ioctl_fibmap(struct file *filp, int __user *p) +{ + struct address_space *mapping = filp->f_mapping; + int res, block; + + /* do we support this mess? */ + if (!mapping->a_ops->bmap) + return -EINVAL; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + res = get_user(block, p); + if (res) + return res; + lock_kernel(); + res = mapping->a_ops->bmap(mapping, block); + unlock_kernel(); + return put_user(res, p); +} + static int file_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - int error; - int block; struct inode *inode = filp->f_path.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; - error = get_user(block, p); - if (error) - return error; - lock_kernel(); - res = mapping->a_ops->bmap(mapping, block); - unlock_kernel(); - return put_user(res, p); - } + return ioctl_fibmap(filp, p); case FIGETBSZ: return put_user(inode->i_sb->s_blocksize, p); case FIONREAD: @@ -87,6 +89,57 @@ static int file_ioctl(struct file *filp, unsigned int cmd, return vfs_ioctl(filp, cmd, arg); } +static int ioctl_fionbio(struct file *filp, int __user *argp) +{ + unsigned int flag; + int on, error; + + error = get_user(on, argp); + if (error) + return error; + flag = O_NONBLOCK; +#ifdef __sparc__ + /* SunOS compatibility item. */ + if (O_NONBLOCK != O_NDELAY) + flag |= O_NDELAY; +#endif + if (on) + filp->f_flags |= flag; + else + filp->f_flags &= ~flag; + return error; +} + +static int ioctl_fioasync(unsigned int fd, struct file *filp, + int __user *argp) +{ + unsigned int flag; + int on, error; + + error = get_user(on, argp); + if (error) + return error; + flag = on ? FASYNC : 0; + + /* Did FASYNC state change ? */ + if ((flag ^ filp->f_flags) & FASYNC) { + if (filp->f_op && filp->f_op->fasync) { + lock_kernel(); + error = filp->f_op->fasync(fd, filp, on); + unlock_kernel(); + } else + error = -ENOTTY; + } + if (error) + return error; + + if (on) + filp->f_flags |= FASYNC; + else + filp->f_flags &= ~FASYNC; + return error; +} + /* * When you add any new common ioctls to the switches above and below * please update compat_sys_ioctl() too. @@ -97,8 +150,8 @@ static int file_ioctl(struct file *filp, unsigned int cmd, int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned long arg) { - unsigned int flag; - int on, error = 0; + int error = 0; + int __user *argp = (int __user *)arg; switch (cmd) { case FIOCLEX: @@ -110,43 +163,11 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, break; case FIONBIO: - error = get_user(on, (int __user *)arg); - if (error) - break; - flag = O_NONBLOCK; -#ifdef __sparc__ - /* SunOS compatibility item. */ - if (O_NONBLOCK != O_NDELAY) - flag |= O_NDELAY; -#endif - if (on) - filp->f_flags |= flag; - else - filp->f_flags &= ~flag; + error = ioctl_fionbio(filp, argp); break; case FIOASYNC: - error = get_user(on, (int __user *)arg); - if (error) - break; - flag = on ? FASYNC : 0; - - /* Did FASYNC state change ? */ - if ((flag ^ filp->f_flags) & FASYNC) { - if (filp->f_op && filp->f_op->fasync) { - lock_kernel(); - error = filp->f_op->fasync(fd, filp, on); - unlock_kernel(); - } else - error = -ENOTTY; - } - if (error != 0) - break; - - if (on) - filp->f_flags |= FASYNC; - else - filp->f_flags &= ~FASYNC; + error = ioctl_fioasync(fd, filp, argp); break; case FIOQSIZE: