long udf_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = filp->f_dentry->d_inode; long old_block, new_block; int result = -EINVAL; if (inode_permission(inode, MAY_READ) != 0) { udf_debug("no permission to access inode %lu\n", inode->i_ino); result = -EPERM; goto out; } if (!arg) { udf_debug("invalid argument to udf_ioctl\n"); result = -EINVAL; goto out; } switch (cmd) { case UDF_GETVOLIDENT: if (copy_to_user((char __user *)arg, UDF_SB(inode->i_sb)->s_volume_ident, 32)) result = -EFAULT; else result = 0; goto out; case UDF_RELOCATE_BLOCKS: if (!capable(CAP_SYS_ADMIN)) { result = -EACCES; goto out; } if (get_user(old_block, (long __user *)arg)) { result = -EFAULT; goto out; } result = udf_relocate_blocks(inode->i_sb, old_block, &new_block); if (result == 0) result = put_user(new_block, (long __user *)arg); goto out; case UDF_GETEASIZE: result = put_user(UDF_I(inode)->i_lenEAttr, (int __user *)arg); goto out; case UDF_GETEABLOCK: result = copy_to_user((char __user *)arg, UDF_I(inode)->i_ext.i_data, UDF_I(inode)->i_lenEAttr) ? -EFAULT : 0; goto out; } out: return result; }
/* * udf_ioctl * * PURPOSE * Issue an ioctl. * * DESCRIPTION * Optional - sys_ioctl() will return -ENOTTY if this routine is not * available, and the ioctl cannot be handled without filesystem help. * * sys_ioctl() handles these ioctls that apply only to regular files: * FIBMAP [requires udf_block_map()], FIGETBSZ, FIONREAD * These ioctls are also handled by sys_ioctl(): * FIOCLEX, FIONCLEX, FIONBIO, FIOASYNC * All other ioctls are passed to the filesystem. * * Refer to sys_ioctl() in fs/ioctl.c * sys_ioctl() -> . * * PRE-CONDITIONS * inode Pointer to inode that ioctl was issued on. * filp Pointer to file that ioctl was issued on. * cmd The ioctl command. * arg The ioctl argument [can be interpreted as a * user-space pointer if desired]. * * POST-CONDITIONS * <return> Success (>=0) or an error code (<=0) that * sys_ioctl() will return. * * HISTORY * July 1, 1997 - Andrew E. Mileski * Written, tested, and released. */ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { long old_block, new_block; int result = -EINVAL; if (file_permission(filp, MAY_READ) != 0) { udf_debug("no permission to access inode %lu\n", inode->i_ino); return -EPERM; } if (!arg) { udf_debug("invalid argument to udf_ioctl\n"); return -EINVAL; } switch (cmd) { case UDF_GETVOLIDENT: return copy_to_user((char __user *)arg, UDF_SB_VOLIDENT(inode->i_sb), 32) ? -EFAULT : 0; case UDF_RELOCATE_BLOCKS: if (!capable(CAP_SYS_ADMIN)) return -EACCES; if (get_user(old_block, (long __user *)arg)) return -EFAULT; if ((result = udf_relocate_blocks(inode->i_sb, old_block, &new_block)) == 0) result = put_user(new_block, (long __user *)arg); return result; case UDF_GETEASIZE: result = put_user(UDF_I_LENEATTR(inode), (int __user *)arg); break; case UDF_GETEABLOCK: result = copy_to_user((char __user *)arg, UDF_I_DATA(inode), UDF_I_LENEATTR(inode)) ? -EFAULT : 0; break; } return result; }