Pointer in struct issue - c

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

Related

Problems with if ....==NULL in C

I have this code, note that it is shortened down. The problem is if the file exists
it still overwrites it. Been 30 years since I did any programming so bear with me. Thanks!
FILE *openFil(FILE *open, char namn[]);
int main(int argc, const char * argv[])
{
FILE *openFil(FILE *open, char namn[]);
FILE *anmal =NULL;
char filNamn[] = "ANMAL.DAT";
postTypAnm pAnm;
anmal = openFil(anmal, filNamn);
}
FILE *openFil(FILE *pointer, char name[])
{
if ((pointer =fopen(name, "r+b"))== NULL)
if ((pointer =fopen(name, "w+b"))== NULL)
{
/* It Enters here as well, but it should not do that or????? */
printf("error\n");
exit(0);
}
return pointer;
}
If you're using the C11 standard you can use the "x" argument to specify that if the file exists the fopen() function will fail.
For reference: http://www.cplusplus.com/reference/cstdio/fopen/
Here's a working example.
#include <errno.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
bool openFile(FILE **ptr,
const char *fileName);
int main(int argc, const char * argv[]) {
FILE *anmal = NULL;
const char *fileName = "ANMAL.DAT";
if(!openFile(&anmal, fileName)) {
exit(EXIT_FAILURE);
}
}
bool openFile(FILE **ptr,
const char *fileName)
{
*ptr = fopen(fileName, "w+bx");
if(!*ptr) {
perror("Error opening file: ");
return false;
}
return true;
}
This is using the x extension in GNU C to test whether the file exists.
As other people have pointed out, there are numerous problems in your original code.
You've redeclared the function prototype for openFil within main.
In openFil there's no point in both accepting the FILE pointer as
a parameter and overwriting it with the return value. Especially if
you're expecting to input a NULL pointer and use the function to
initialise it. Either use a pointer-to-pointer as a parameter so you
can modify the pointer within the function, or ignore it completely
and set its value with the function's return value. Not both.
You're not actually testing for whether the file exists at all. According to the manual pages for fopen (man fopen) neither of the flags you used in opening the file (r+ and w+) care whether the file exists. r+ opens for reading/writing and always positions the stream at the beginning of the file. w+ opens for reading/writing, truncating the file if it exists already. This explains why you didn't get the effect you intended.
1.
"It Enters here as well, but it should not do that or?????"
No, It shouldn´t. If both pointers are NULL the opening of the streams to ANMAL.DAT were not successful, neither in w+b nor in r+b mode. Proof if the file really exist in the directory of the executable. Else try to use the entire path from the root directory to the file.
"The problem is if the file exists it still overwrites it."
Why do you know that the file is really overwritten in a proper manner?
Since if ((pointer =fopen(name, "r+b")) == NULL) and if ((pointer = fopen(name, "w+b"))== NULL) both fail, it seems that the ANMAL.DAT does not exist where fopen() searches for it or otherwise an error occurs when trying to open it (maybe has incorrect format or is corrupted?).
Place perror(name) in the error routine to check if errno was set to indicate an error at name.
2.
In the error routine: exit(0) is not correct if an error has happened. Use exit(EXIT_FAILURE).
Side note:
You have another prototype for the function openFil-> FILE *openFil(FILE *open, char namn[]); inside of main, which is redundant.
Also the identifier of the second parameter is different in the prototype before main to the identifier at the definition of openFil, namn in comparison to name.

Stub system function in google test

I am trying to use Google Test to test C code but I am encounter some problem related to write stub for system functions like: fopen,fclose,fread,fwrite, memcpy,memset,stat,...I don't known how to stub them correctly to cover all branchs in function that need to be tested.
Example , I have a function, how to test it by stub fopen, fclose, fwrite, fread?
Only Stub, not Mock.
#include <stdio.h>
#include <stdlib.h>
int main(){
FILE *f;
//initialize the arr1 with values
int arr1[5]={1,2,3,4,5};
int arr2[5];
int i=0;
//open the file for write operation
if((f=fopen("includehelp.txt","w"))==NULL){
//if the file does not exist print the string
printf("Cannot open the file...");
exit(1);
}
//write the values on the file
if((fwrite(arr1,sizeof(int),5,f))!=5){
printf("File write error....\n");
}
//close the file
fclose(f);
//open the file for read operation
if((f=fopen("includehelp.txt","r"))==NULL){
//if the file does not exist print the string
printf("Cannot open the file...");
exit(1);
}
//read the values from the file and store it into the array
if((fread(arr2,sizeof(int),5,f))!=5){
printf("File write error....\n");
}
fclose(f);
printf("The array content is-\n");
for(i=0;i<5;i++){
printf("%d\n",arr2[i]);
}
return 0;
}
Your file() function in sample.c calls fopen(). Defining fopen as something else in a totally different file (compilation unit) is not going to change that.
You cannot simply mock a free function.
You can change the file() function to take a pointer to the fopen() function to use. In your tests you then provide a pointer to your mock function when calling the file() function. This is a form of dependency injection.
Another option is to use conditional compilation.
An example of using dependency injection:
// Typedef for our "fopen interface". Makes our code a bit more readable.
typedef FILE *(*fopen_type)(const char *, const char *);
FILE *file(fopen_type fopen_func)
{
FILE *f = fopen_func("abc", "r"); // Call the provided "fopen" function.
return f; // Let's return the opened file or `NULL`.
}
And then in your test code:
TEST(OPEN_FILE, OK)
{
ASSERT_NE(NULL, file(&my_fopen));
}
If you use many system functions that you want to mock, you can also create a struct that contains pointers to all the relevant functions.
struct system_calls {
fopen_type fopen;
// Add more system calls here.
};
FILE *file(struct system_calls *p)
{
FILE *f = p->fopen("abc", "r");
return f;
}
The premise here is that if you want to test your code, you need to write testable code. Dependency injection is one way to achieve that.

Casting to a File Pointer

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

C Filling a buffer

I need to fill a buffer space with file descriptors of files from a defined source directory. So I have the startup code:
int main(int argc, char* argv[])
{
DIR *src=opendir(argv[1]);
struct dirent *DirEntry;
char* buffer[200];
do {
DirEntry = readdir(src);
if(DirEntry != NULL) {
//put file into buffer
}
}while(DirEntry!=NULL);
}
How do I complete this loop to place all file descriptors of a given directory into the array called 'buffer'? Should I use an object of DirEntry like DirEntry->d_name to return a file descriptor that I then put into the array?
If you need to move files from a source directory to a destination directory, you are going to need file names much more than you need file descriptors. With the names, you can open and close descriptors whenever needed; without the names, you can't create the files in the target directory sensibly. However, we can handle file descriptors too.
So, assuming you have strdup(), you might use:
typedef struct File
{
char *name;
int fd;
} File;
And in your loop:
if (DirEntry != NULL)
{
buffer[i].name = strdup(DirEntry->d_name);
if (buffer[i].name != 0)
buffer[i].fd = open(buffer[i].name, O_RDONLY);
i++;
}
where buffer is an array of File and i is a convenient integer:
enum { MAX_FILES = 4096 };
int i;
File buffer[MAX_FILES];
You should also add a condition to the main condition to ensure no overflow (or replace the fixed size buffer with a dynamically allocated one):
if (DirEntry != NULL && i < MAX_FILES)
You could sensibly break the loop if i reaches the limit. You could test whether the name represents a file (as opposed to FIFO, block device, character device, socket, symlink, directory, ...); you'd probably use stat() or lstat() for that. The file descriptor would be negative (-1) if the open() call failed. You might conserve entries by not incrementing i if the memory allocation fails, but it is probably not worth worrying about. If the memory allocation for a file name fails, there isn't going to be much else that works.
A file descriptor is "int" typed value that returned by open() system call. It's not in DirEntry structure. So, firstly, you should define the buffer array as int type, then you can open each file in the loop with open() system call, and save open() returned file descriptor in buffer array.
You question doesn't quite make sense. If you want file descriptors you have to open the file or directory with open() to get a file descriptor.
If you just want to store the names of the files in an array, then you can create a two dimensional array using malloc or calloc and copy the d_name member to the next available slot in the array. Alternatively you can use what you have and use a function such as strdup to copy the string to your array, but be careful because you'll need to free it later using free().
If you actually do want file descriptors, you will need to create an array of int rather than char *.

How can I get a filename from a file descriptor inside a kernel module?

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?
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 *.

Resources