Reputation: 11
I am writing my own procfs read write handler.
static ssize_t mywrite(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos)
{
printk(KERN_ALERT "write handler\n");
int num,c,i,m;
char buf[BUFSIZE];
if(*ppos > 0 || count > BUFSIZE){
printk(KERN_ALERT "failed *ppos > 0 || count > BUFSIZE");
return -EFAULT;
}
if(copy_from_user(buf, ubuf, count)){
printk(KERN_ALERT "FAILED copy_from_user(buf, ubuf, count)");
return -EFAULT;
}
int characters_in_input = strlen(buf);
printk(KERN_INFO "wrote %s in file and it's length is %d \n",buf,characters_in_input);
return characters_in_input;
}
static ssize_t myread(struct file *file, char __user *ubuf,size_t count, loff_t *ppos)
{
some logic
}
static struct file_operations myops =
{
.owner = THIS_MODULE,
.read = myread,
.write = mywrite,
};
static int simple_init(void)
{
ent=proc_create("mydev",0777,NULL,&myops);
printk(KERN_ALERT "hello...\n");
return 0;}
And when I write smth from c code like
int fd = open("/proc/mydev", O_RDWR);
lseek(fd, 0 , SEEK_SET);
if(write(fd, "1", 10)==-1){
printf("write failed");
};
handler output is "wrote 1 in file and it's length is 1 " but if I use bash and execute
echo "asd" > /proc/mydev
handler output is "wrote asd
\xa8B\x99ٚ\xff\xff\xa6\xb9\xff\xff\xff\xff辠Z\xb2\xff\xff in file and it's length is 28 "
Upvotes: 0
Views: 141
Reputation: 881633
Re your code:
int characters_in_input = strlen(buf);
There's nothing requiring a caller to terminate their data with a \0
, which is what would be needed for strlen
to work properly:
Your C code uses "1"
which is stored in memory as the characters 1
and \0
, and a length of 10. Hence the \0
will be there.
However, the echo
command will send four characters: a
, s
, d
, and \n
with a length of four. It will not send a \0
.
You can confirm the echo
behaviour with something like:
/home/pax> echo asd | xxd
00000000: 6173 640a
It's also evident by what your program logged (from your question):
wrote asd
\xa8B\x99ٚ\xff\xff\xa6\xb9\xff\xff\xff\xff辠Z\xb2\xff\xff in file and it's length is 28
That has the asd
and the \n
newline, followed by a lot lot of arbitrary bytes that are beyond what you provided, because both printf("%s")
and strlen()
expect a properly terminated C string.
In fact, the whole point of the count
parameter is so that you can operate with binary data rather than strings. It allows you to send data with embedded \0
characters and have them treated correctly.
So I would be using that rather than trying to work out how long the data is.
Upvotes: 2