I need to get the name of a file from a given file descriptor, inside a small linux kernel module that I wrote. I tried the solution given at Getting Filename from file descriptor in C, but for some reason, it prints out garbage values (on using readlink
on /proc/self/fd/NNN
as mentioned in the solution). How can I do it?
You can use readlink on /proc/self/fd/NNN where NNN is the file descriptor. This will give you the name of the file as it was when it was opened — however, if the file was moved or deleted since then, it may no longer be accurate (although Linux can track renames in some cases).
All file descriptors that a process contains are stored in the directory /proc/PID/fd/ . We had already talked a bit about the /proc file system. This directory holds information about processes. Every process has a directory in this filesystem and stores its relevant data within that directory.
No it is not. PID is process identifier, and file descriptor is file handler identifier.
In Linux/Unix, everything is a file. Regular file, Directories, and even Devices are files. Every File has an associated number called File Descriptor (FD). Your screen also has a File Descriptor.
Don't call SYS_readlink
- use the same method that procfs
does when one of those links is read. Start with the code in proc_pid_readlink()
and proc_fd_link()
in fs/proc/base.c
.
Broadly, given an int fd
and a struct files_struct *files
from the task you're interested in (which you have taken a reference to), you want to do:
char *tmp;
char *pathname;
struct file *file;
struct path *path;
spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (!file) {
spin_unlock(&files->file_lock);
return -ENOENT;
}
path = &file->f_path;
path_get(path);
spin_unlock(&files->file_lock);
tmp = (char *)__get_free_page(GFP_KERNEL);
if (!tmp) {
path_put(path);
return -ENOMEM;
}
pathname = d_path(path, tmp, PAGE_SIZE);
path_put(path);
if (IS_ERR(pathname)) {
free_page((unsigned long)tmp);
return PTR_ERR(pathname);
}
/* do something here with pathname */
free_page((unsigned long)tmp);
If your code is running in process-context (eg. invoked through a syscall) and the file descriptor is from the current process, then you can use current->files
for the current task's struct files_struct *
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With