I'm setting up the FUSE filesystem, and I need to get a file pointer to any open files so that I can encrypt them as they get written. The FUSE system uses a special struct. One of the components of the struct is called fh and is of type uint64_t. When a file is opened, it is captured in an int variable as you can see in the following code:
/* File open operation */
int bb_open(const char *path, struct fuse_file_info *fi)
{
int fd;
fd = open(path, fi->flags);
fi->fh = fd;
return fd;
}
This fi struct is available to me in the write function, and I'm hoping that I can use it to create a file pointer that I can pass to my encryption function. Here is the code for the write function as I have it set up at the moment:
/* Write data to an open file */
int bb_write(const char *path, const char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
char* password;
FILE* fp;
//malloc and instantiate password
fp = (FILE*) fi->fh; //my lame attempt to get a file pointer
return encrypt(<inpFilePtr>, <outFilePtr>, 1, password);
}
Finally, the signature of my encryption function looks like this:
extern int encrypt(FILE* in, FILE* out, int action, char* key_str);
I'd like to take that fi->fh variable and turn it into a file pointer so that I can use it as my input file pointer argument. Since it was originally created by an "open" operation, it seems like there should be a way to do this, but I can't make it work.
Can anyone help? Thanks!
File descriptors and FILE * pointers aren't the same thing. A FILE * pointer is a pointer to an opaque type provided by your C implementation - the APIs that deal with FILE * (fopen, fread, fwrite, fclose, etc.) are part of standard C. File descriptors, on the other hand, are operated on using the POSIX system calls (open, read, write, close, etc.) that are often used to implement the C-level abstractions.
Luckily there are functions that let you get one from the other. In your case, you'll want to use fdopen(3) to get a FILE * from the file descriptor. If you wanted to go the other way, you'd want to look into fileno(3).
Related
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Getting Filename from file descriptor in C
Is there a simple and (reasonably) portable way of getting the filename from a FILE*?
I open a file using f = fopen(filename, ...) and then pass down f to various other functions, some of which may report an error. I'd like to report the filename in the error message but avoid having to pass around the extra parameter.
I could create a custom wrapper struct { FILE *f, const char *name }, but is there perhaps a simpler way? (If the FILE* wasn't opened using fopen I don't care about the result.)
On some platforms (such as Linux), you may be able to fetch it by reading the link of /proc/self/fd/<number>, as so:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
char path[1024];
char result[1024];
/* Open a file, get the file descriptor. */
FILE *f = fopen("/etc/passwd", "r");
int fd = fileno(f);
/* Read out the link to our file descriptor. */
sprintf(path, "/proc/self/fd/%d", fd);
memset(result, 0, sizeof(result));
readlink(path, result, sizeof(result)-1);
/* Print the result. */
printf("%s\n", result);
}
This will, on my system, print out /etc/passwd, as desired.
It's a bit difficult, because a FILE* can read/write from a file handle which isn't associated with a named file at all (for example an unnamed pipe or a socket). You can obtain the file handle with fileno() and then there are system specific ways to learn about the file name. Here's a discussion on how to do this under Linux:
Getting Filename from file descriptor in C
and under Windows this isn't much easier either:
http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx (as an extra step here, you use _get_osfhandle() to get the Windows file handle from the c-library file descriptor)
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".
I have probably pointer problem with fp, cause I get (SIGSEGV) error.
But I'm not much experienced in C and I doesn't see it.
What I'm trying to do. I do Server application for simple game, I handle clients in new threads. I use function pthread_create, it has handle function called handle_client, I need to get in some argumets socketdescritpor(it works) and filedescriptor for writing logs(there is probably the problem).
In my main I open the log file, then I put the filedescriptor to my struct, I get the struct inside the handle_client function and in this function I want to get back the file decriptor (fp) of the log file, to be able write to file. I use fflush(fp) to save the data after each fprintf, I open the file once and then each client should be able write to file throuhgt this descripor, but I've probably done something bad with pointers (I mean geting fp in and out from the struct, there is piece of my code where I do this action.) Thx for help.
struct
typedef struct
{
int fd;
FILE *fp; //filepointer for logs file
} my_thread_context_t;
main
int main(int argc, char *argv[]) {
FILE * fp;
fp = fopen("Serverlog.log","w");//delete last file
fclose(fp);
fp = fopen("Serverlog.log","a+");
my_thread_context_t ctx;
//bind server
//listen
while(1) {
//accept
ctx.fp = fp;// add file pointer to structure
int check = pthread_create(&thread, NULL,handle_client,&ctx);
//other code
}
hadle_client function
void * handle_client(void * void_context){
my_thread_context_t * context = (my_thread_context_t *) void_context;
FILE *fp; //pointer na soubor s logy
fp = context->fp;//get the filepointer for logs
//other code ..
}
It looks like many threads can access your my_thread_context_t::fp and that is exactly the problem. The FILE* type is really a (opaque) pointer to structure used by the C library. This structure contents may get corrupted (or non-consistent) when more than one thread modifies it. You must synchronize access to your my_thread_context_t::fp. I would suggest creating a mutex (see pthread_mutex_init, pthread_mutex_lock, pthread_mutex_unlock) inside your ctx structure. Each thread should lock it before it starts writing to a file and unlock it when its finished writing - a separate (inline) function for this puprpose would be even better design, e.g:
typedef struct
{
int fd;
pthread_mutex_t mutex;
FILE *fp; //filepointer for logs file
} my_thread_context_t;
my_thread_context_t ctx;
fp = fopen("Serverlog.log","a+");
pthread_mutex_init(&ctx.mutex);
ctx.fp = fp;
inline void write_to_log(my_thread_context_t* pCtx,const char* pcszMessage)
{
pthread_mutex_lock(&(pCtx->mutex));
/* here write to the log file */
pthread_mutex_unlock(&(pCtx->mutex));
}
If you do it this way, it is not only safe, but you also do not have to invoke fflush
after every write (unless you want your log to be always in sync).
Don't forget to call pthread_mutex_destroy after all threads are finished (e.g. after all neccesary ptrhead_joins).
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Getting Filename from file descriptor in C
Is there a simple and (reasonably) portable way of getting the filename from a FILE*?
I open a file using f = fopen(filename, ...) and then pass down f to various other functions, some of which may report an error. I'd like to report the filename in the error message but avoid having to pass around the extra parameter.
I could create a custom wrapper struct { FILE *f, const char *name }, but is there perhaps a simpler way? (If the FILE* wasn't opened using fopen I don't care about the result.)
On some platforms (such as Linux), you may be able to fetch it by reading the link of /proc/self/fd/<number>, as so:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(void)
{
char path[1024];
char result[1024];
/* Open a file, get the file descriptor. */
FILE *f = fopen("/etc/passwd", "r");
int fd = fileno(f);
/* Read out the link to our file descriptor. */
sprintf(path, "/proc/self/fd/%d", fd);
memset(result, 0, sizeof(result));
readlink(path, result, sizeof(result)-1);
/* Print the result. */
printf("%s\n", result);
}
This will, on my system, print out /etc/passwd, as desired.
It's a bit difficult, because a FILE* can read/write from a file handle which isn't associated with a named file at all (for example an unnamed pipe or a socket). You can obtain the file handle with fileno() and then there are system specific ways to learn about the file name. Here's a discussion on how to do this under Linux:
Getting Filename from file descriptor in C
and under Windows this isn't much easier either:
http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx (as an extra step here, you use _get_osfhandle() to get the Windows file handle from the c-library file descriptor)