I need to implement the following function as part of a kernel module:
ssize_t write(struct file *filp, const char *buf, size_t count, loff_t *f_pos)
which writes buf into the file filp using f_pos, and then updates f_pos.
my question is how can I write to f_pos and then change it's value?
I understand that it points to the start of the free file space but how can I update it after i'm done writing?
Thank you
Related
static ssize_t read(struct file *file, char *buff, size_t len, loff_t *offset)
{
printk(KERN_INFO "write\n");
return simple_read_from_buffer(buff, len, offset, ker_buff, SIZE);
}
static ssize_t write(struct file *file, const char *buff, size_t len, loff_t *offset)
{
printk(KERN_INFO "read\n");
printk(KERN_INFO "your offset is:%lu\n",(long)offset);
return simple_write_to_buffer(ker_buff, SIZE, offset, buff, len);
}
when I perform echo "hi" > /dev/device_name I am getting output:
read
your offset is 0 as output.`
Why am I getting 0?
In man page its mentioned as user's offset position.
Can any one explain me what is the use of offset?
The "offset position" is the position in the file where the user-space code is reading or writing. When you do echo "hi" > /dev/device_name, you are writing to the beginning of the file, which is position 0. You could test writing to a different position from the command line by using, for example, echo "hi" | dd of=/dev/device_name seek=2000
Note: you need to update this yourself. If the user-space code writes 4000 bytes, you should increment *offset by 4000. Otherwise, if they write another 4000 bytes after that, *offset will still be 0 and they'll overwrite the first 4000 bytes instead of the next 4000.
I am just trying to read the data of a file into memory, but I want that my programme uses as less system calls as possible. That means that I am trying to avoid open or openat. I only want to use read. But I cannot find out how I can do that. Can someone help me?
Thanks!
read requires an open file descriptor, which you cannot get without calling either open or openat with the only exception being if you read from stdin (fd 0).
Updated to add:
Thankyou #Yunnosch for the suggestion. How about this:
http://pubs.opengroup.org/onlinepubs/009695399/functions/read.html
NAME
pread, read - read from a file
SYNOPSIS
#include <unistd.h>
[XSI] [Option Start] ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); [Option End]
ssize_t read(int fildes, void *buf, size_t nbyte);
DESCRIPTION
The read() function shall attempt to read nbyte bytes from the file associated with the open file descriptor, fildes, into the buffer pointed to by buf.
I'd like to share a variable between kernel and user space and I've found that it's possible with procfs.
The kernel module must act in certain way if given value is set. The user space program is responsible for changing this value, but the kernel module must read it when necessary.
I know that I must create the /proc file in the kernel module.
My question is, how to read the file from the kernel module?
Source : linux.die.net/lkmpg/x769.html
/**
* This function is called with the /proc file is written
*
*/
int procfile_write(struct file *file, const char *buffer, unsigned long count,
void *data)
{
/* get buffer size */
procfs_buffer_size = count;
if (procfs_buffer_size > PROCFS_MAX_SIZE ) {
procfs_buffer_size = PROCFS_MAX_SIZE;
}
/* write data to the buffer */
if ( copy_from_user(procfs_buffer, buffer, procfs_buffer_size) ) {
return -EFAULT;
}
return procfs_buffer_size;
}
To clarify, in Your module whenever user writes to Your file in procfs, this example shows how to handle such write.
In kernel >= 3.10 proc_write is moved to structure file_operations where declaration of write is different, so in newest your solution won't work.
You can implement typical file_operations.write(struct file *, const char __user *, size_t, loff_t *) and reference this to:
struct proc_dir_entry your_proc_dir_entry{
.proc_fops = &your_fops,
}
I want to know on what file in /sys/* the functionstatic ssize_t
sysfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos) were called. the question is how to get the file name/path by having struct file *file ?
struct file {
mode_t f_mode;
loff_t f_pos;
unsigned short f_flags;
unsigned short f_count;
unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
struct file *f_next, *f_prev;
int f_owner; /* pid or -pgrp where SIGIO should be sent */
struct inode * f_inode;
struct file_operations * f_op;
unsigned long f_version;
void *private_data; /* needed for tty driver, and maybe others */
};
EDIT:
I understand there is no one-to-one mapping between inode to a name, but I must know the major/minor/file descriptor and can search for some of the inode's name in the file system.
Actuall you can retrieve the file path used to open the file. In linux struct file represents an opened file and has the path used to open that file associate with the structure. Before 2.6.20 it was a member called f_dentry and from 2.6.20 it is a new member called f_path. You can use function d_path() to retrieve the full path of your file directly.
Refer to the following Linux source code:
http://lxr.free-electrons.com/source/include/linux/fs.h?v=3.10#L763
http://lxr.free-electrons.com/source/fs/dcache.c?v=3.0#L2626
And also answer:
How can I get a filename from a file descriptor inside a kernel module?
In Linux and other Unix-like OSs, a file object can be pointed to by any number of names, and the file object itself has no pointers back to any of them. Names are not a feature of the file, they are just an external index.
Given a struct file, is it possible to get the associated file descriptor in linux kernel space? I am trying to change permissions using either sys_chmod or sys_fchmod. One takes a file descriptor the other expects a filename from user space. I can figure out how to get the filename but how would I cast it to a user space pointer?
Thanks
The function you're after is chmod_common:
static int chmod_common(struct path *path, umode_t mode)
Which takes a path and the mode you want to set. Unfortunately, as you noticed, it's static and obviously not exported. So you could go multiple ways:
Replicate whatever it does in a function of your own
Get "the file descriptor" from struct file (ugly)
Find a way to call sys_chmod
Now sys_chmod expects a user pointer but you're in the kernel. Here's what you could do to trick it:
mm_segment_t oldfs = get_fs();
char __user *userptr;
userptr = (char __user __force *) kernptr;
set_fs(KERNEL_DS);
/* call sys_chmod */
set_fs(oldfs);
All this is very much in line with "things you never should do in the Kernel".