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 );