Writing more data than pagesize into /proc

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

I have a problem writing more data than a pagesize into /proc.
I use this function:
> static int testfile_Write( struct file *Instanz, const char __user *UserBuffer, unsigned long count, void  *data )
But if the user writes more than a pagesize of data - the functions is called again.

So I tried do use void *data to distinguish if it's a subsequent call or not.
However -  data isn't stored properly.
Unlike the paramters in the read-function
> static int testfile_Read( char *buf, char **start, off_t offset, int size, int *eof, void *data)
data is always NULL.

In short I have two questions and one very simple one..
1) What's wrong in my code that I get data back as NULL?
2) How can I check if the user has all data written?
3) How can I take use of the struct file*? And where do I find it's members?


Thanks in advance.

I attached the code and I send it inline so you can directly correct me.
> #include <linux/module.h>
> #include <linux/version.h>
> #include <linux/proc_fs.h>
> #include <linux/init.h>
> #include <linux/stat.h>
> #include <linux/kernel.h>
> #include <asm/uaccess.h>
> 
> MODULE_LICENSE("GPL");
> MODULE_AUTHOR("Johannes Held; uni@xxxxxxxxx");
> MODULE_DESCRIPTION("FAPS /proc Tester");
> 
> static struct proc_dir_entry *ProcDir, *ProcFile;
> 
> static unsigned long datalen = 0;
> static char* daten;
> 
> static int testfile_Read( char *buf, char **start, off_t offset, int size, int *eof, void *data)
> {
> 	int written = 0;	
> 	
> 	if(daten == NULL || offset >= datalen) {
> 		if(data) {
> 			kfree(data);
> 			data = NULL;
> 		}
> 		*eof = 1;
> 		return 0;
> 	}
> 	
> 	if(offset == 0) {
> 		data = kmalloc(datalen * sizeof(char), GFP_KERNEL);
> 		memcpy(data, daten, datalen);
> 	}
>  	
> 
> 	if(datalen <= size) {
> 		written = datalen;
> 		memcpy(buf, data, written);	
> 	}
> 	else {
> 		written = datalen - offset;
> 		written = (written < size) ? written : size;
> 		memcpy(buf, data+offset, written);
> 		*start = buf; 
> 	}
> 	return written;
> }
> 
> static int testfile_Write( struct file *Instanz, const char __user *UserBuffer,
>                 unsigned long count, void  *data )
> {
> 	int notCopied = 0;
> 	char * newData = NULL;
> 	jSAYNAME
> 	if(data == NULL) {
> 		if(daten) {
> 			kfree(daten);
> 		}
> 		daten = (char*)kmalloc( count, GFP_KERNEL );
> 		if( daten == NULL )
>     		return -ENOMEM;
> 		data = daten;
> 	}
> 	else {
> 		newData = (char*)kmalloc(datalen+count, GFP_KERNEL);
> 		if(newData == NULL)
> 			return -ENOMEM;
> 		memcpy(newData, daten, datalen);
> 		kfree(daten);
> 		daten = newData;
> 		data = daten;
> 	}
> 
> 	notCopied = copy_from_user( daten+datalen, UserBuffer, count );
> 	datalen+=count;
> 	ProcFile->size += count-notCopied;
> 	return count - notCopied;
> }
> 
> static int __init jProcTestInit(void)
> {
> 	ProcDir = proc_mkdir( "jProcTest", NULL );
> 	ProcFile = create_proc_entry("testfile", S_IRUGO, ProcDir );
>    	if ( ProcFile ) {
>     	ProcFile->read_proc = testfile_Read;
> 			ProcFile->write_proc = testfile_Write;
>       ProcFile->data = NULL;
>     }
>     return 0;
> }
> 
> static void __exit jProcTestExit(void)
> {
> 	if(daten)
> 		kfree(daten);
> 	if ( ProcFile )
> 		remove_proc_entry( "testfile", ProcDir );
> 	if ( ProcDir )
> 		remove_proc_entry( "jProcTest", NULL );
> }
> 
> module_init( jProcTestInit );
> module_exit( jProcTestExit );

-- 
Gruß, Johannes
http://www.hehejo.de
#include <linux/module.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <linux/stat.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Johannes Held; uni@xxxxxxxxx");
MODULE_DESCRIPTION("FAPS /proc Tester");

static struct proc_dir_entry *ProcDir, *ProcFile;

static unsigned long datalen = 0;
static char* daten;

static int testfile_Read( char *buf, char **start, off_t offset, int size, int *eof, void *data)
{
	int written = 0;	
	
	if(daten == NULL || offset >= datalen) {
		if(data) {
			kfree(data);
			data = NULL;
		}
		*eof = 1;
		return 0;
	}
	
	if(offset == 0) {
		data = kmalloc(datalen * sizeof(char), GFP_KERNEL);
		memcpy(data, daten, datalen);
	}
 	

	if(datalen <= size) {
		written = datalen;
		memcpy(buf, data, written);	
	}
	else {
		written = datalen - offset;
		written = (written < size) ? written : size;
		memcpy(buf, data+offset, written);
		*start = buf; 
	}
	return written;
}

static int testfile_Write( struct file *Instanz, const char __user *UserBuffer,
                unsigned long count, void  *data )
{
	int notCopied = 0;
	char * newData = NULL;
	jSAYNAME
	if(data == NULL) {
		if(daten) {
			kfree(daten);
		}
		daten = (char*)kmalloc( count, GFP_KERNEL );
		if( daten == NULL )
    		return -ENOMEM;
		data = daten;
	}
	else {
		newData = (char*)kmalloc(datalen+count, GFP_KERNEL);
		if(newData == NULL)
			return -ENOMEM;
		memcpy(newData, daten, datalen);
		kfree(daten);
		daten = newData;
		data = daten;
	}

	notCopied = copy_from_user( daten+datalen, UserBuffer, count );
	datalen+=count;
	ProcFile->size += count-notCopied;
	return count - notCopied;
}

static int __init jProcTestInit(void)
{
	ProcDir = proc_mkdir( "jProcTest", NULL );
	ProcFile = create_proc_entry("testfile", S_IRUGO, ProcDir );
   	if ( ProcFile ) {
    	ProcFile->read_proc = testfile_Read;
			ProcFile->write_proc = testfile_Write;
      ProcFile->data = NULL;
    }
    return 0;
}

static void __exit jProcTestExit(void)
{
	if(daten)
		kfree(daten);
	if ( ProcFile )
		remove_proc_entry( "testfile", ProcDir );
	if ( ProcDir )
		remove_proc_entry( "jProcTest", NULL );
}

module_init( jProcTestInit );
module_exit( jProcTestExit );

[Index of Archives]     [Newbies FAQ]     [Linux Kernel Mentors]     [Linux Kernel Development]     [IETF Annouce]     [Git]     [Networking]     [Security]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux SCSI]     [Linux ACPI]
  Powered by Linux