/*------------------------------------------------------------------------------------------*\ * * Copyright (C) 2004 AVM GmbH * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \*------------------------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CONFIG_PROC_FS) #include #endif /*--- #if defined(CONFIG_PROC_FS) ---*/ #include "tffs_local.h" /*-----------------------------------------------------------------------------------------------*\ \*-----------------------------------------------------------------------------------------------*/ int tffs_ioctl(struct inode *inode, struct file *filp, unsigned int ioctl_param, unsigned long argv) { struct _tffs_cmd tffs_cmd; unsigned char *buffer; unsigned int result_size = sizeof(tffs_cmd); unsigned int number = _IOC_NR(ioctl_param); struct _tffs_open *open_data = (struct _tffs_open *)filp->private_data; DBG((KERN_INFO "%s: tffs_ioctl: type %u number %u size %u\n", MODULE_NAME, _IOC_TYPE(ioctl_param), number, _IOC_SIZE(ioctl_param))); if(open_data->id != 0) { /*--- printk(KERN_WARNING "%s: tffs_ioctl: ioctl not supported by minor != 0\n", MODULE_NAME); ---*/ return -EOPNOTSUPP; } if(argv == 0) { printk(KERN_ERR "%s: tffs_ioctl: no data pointer for cmd number %u\n", MODULE_NAME, number); return -EFAULT; } if(copy_from_user(&tffs_cmd, (const void *)argv, sizeof(tffs_cmd))) { printk(KERN_ERR "%s: tffs_ioctl: copy_from_user failed\n", MODULE_NAME); return -EFAULT; } switch(number) { case _TFFS_READ_ID: if((filp->f_flags & O_ACCMODE) == O_WRONLY) { printk(KERN_ERR "%s: tffs_ioctl: read failed: flags=O_WRONLY\n", MODULE_NAME); return -EFAULT; } buffer = kmalloc(tffs_cmd.size, GFP_KERNEL); if(!buffer) { printk(KERN_ERR "%s: tffs_ioctl: alloc(%u) failed\n", MODULE_NAME, tffs_cmd.size); return -EFAULT; } DBG((KERN_DEBUG "%s: tffs_ioctl: read \n", MODULE_NAME)); if(down_interruptible(&tffs_sema)) { kfree(buffer); printk(KERN_ERR "%s: tffs_ioctl(READ): down_interruptible() failed\n", MODULE_NAME); return -ERESTARTSYS; } tffs_cmd.status = TFFS_Read(filp->private_data, tffs_cmd.id, buffer, &tffs_cmd.size); up(&tffs_sema); if(tffs_cmd.status == 0) { if(copy_to_user((void *)tffs_cmd.buffer, buffer, (unsigned long)tffs_cmd.size)) { kfree(buffer); printk(KERN_ERR "%s: tffs_ioctl: copy_to_user failed\n", MODULE_NAME); return -EFAULT; } result_size += tffs_cmd.size; } kfree(buffer); break; case _TFFS_WRITE_ID: if((filp->f_flags & O_ACCMODE) == O_RDONLY) { printk(KERN_ERR "%s: tffs_ioctl: write failed: flags=O_RDONLY\n", MODULE_NAME); return -EFAULT; } buffer = kmalloc(tffs_cmd.size, GFP_KERNEL); if(!buffer) { printk(KERN_ERR "%s: tffs_ioctl: alloc(%u) failed\n", MODULE_NAME, tffs_cmd.size); return -EFAULT; } if(copy_from_user(buffer, (void *)tffs_cmd.buffer, (unsigned long)tffs_cmd.size)) { kfree(buffer); printk(KERN_ERR "%s: tffs_ioctl: copy_from_user failed\n", MODULE_NAME); return -EFAULT; } DBG((KERN_DEBUG "%s: tffs_ioctl: write\n", MODULE_NAME)); if(down_interruptible(&tffs_sema)) { kfree(buffer); printk(KERN_ERR "%s: tffs_ioctl(WRITE): down_interruptible() failed\n", MODULE_NAME); return -ERESTARTSYS; } tffs_cmd.status = TFFS_Write(filp->private_data, tffs_cmd.id, buffer, tffs_cmd.size, 0); up(&tffs_sema); kfree(buffer); break; case _TFFS_FORMAT: DBG((KERN_DEBUG "%s: tffs_ioctl: format\n", MODULE_NAME)); if(down_interruptible(&tffs_sema)) { printk(KERN_ERR "%s: tffs_ioctl(FORMAT): down_interruptible() failed\n", MODULE_NAME); return -ERESTARTSYS; } tffs_cmd.status = TFFS_Format(filp->private_data); up(&tffs_sema); break; case _TFFS_WERKSEINSTELLUNG: DBG((KERN_DEBUG "%s: tffs_ioctl: format\n", MODULE_NAME)); if(down_interruptible(&tffs_sema)) { printk(KERN_ERR "%s: tffs_ioctl(WERKSEINSTELLUNG): down_interruptible() failed\n", MODULE_NAME); return -ERESTARTSYS; } tffs_cmd.status = TFFS_Werkseinstellungen(filp->private_data); up(&tffs_sema); break; case _TFFS_CLEAR_ID: DBG((KERN_DEBUG "%s: tffs_ioctl: clear id\n", MODULE_NAME)); if(down_interruptible(&tffs_sema)) { printk(KERN_ERR "%s: tffs_ioctl(CLEAR_ID): down_interruptible() failed\n", MODULE_NAME); return -ERESTARTSYS; } tffs_cmd.status = TFFS_Clear(filp->private_data, tffs_cmd.id); up(&tffs_sema); break; case _TFFS_CLEANUP: DBG((KERN_DEBUG "%s: tffs_ioctl: cleanup\n", MODULE_NAME)); if(down_interruptible(&tffs_sema)) { printk(KERN_ERR "%s: tffs_ioctl(CLEANUP): down_interruptible() failed\n", MODULE_NAME); return -ERESTARTSYS; } tffs_cmd.status = TFFS_Cleanup(filp->private_data); up(&tffs_sema); break; case _TFFS_REINDEX: DBG((KERN_DEBUG "%s: tffs_ioctl: reindex\n", MODULE_NAME)); if(down_interruptible(&tffs_sema)) { printk(KERN_ERR "%s: tffs_ioctl(REINDEX): down_interruptible() failed\n", MODULE_NAME); return -ERESTARTSYS; } tffs_cmd.status = TFFS_Create_Index(); up(&tffs_sema); break; case _TFFS_INFO: DBG((KERN_DEBUG "%s: tffs_ioctl: info\n", MODULE_NAME)); if(down_interruptible(&tffs_sema)) { printk(KERN_ERR "%s: tffs_ioctl(INFO): down_interruptible() failed\n", MODULE_NAME); return -ERESTARTSYS; } tffs_cmd.status = TFFS_Info(filp->private_data, &tffs_cmd.id); up(&tffs_sema); break; default: printk(KERN_ERR "%s: tffs_ioctl: unknwon\n", MODULE_NAME); return -EINVAL; } if(copy_to_user((void *)argv, &tffs_cmd, sizeof(tffs_cmd))) { printk(KERN_ERR "%s: tffs_ioctl: copy_to_user failed\n", MODULE_NAME); return -EFAULT; } return 0; }