Joseph Smith
Joseph Smith

Reputation: 139

how to avoid segmentation fault when opening file within loop?

When attempting to open a file (defined by event->name) I'm consistently getting a segmentation fault (core dumped). The closest I've got to preventing this issue is by altering "rb" to "r", and removing the hashing function below it - including "fclose(ftest)" - however I'd not consider that progress...

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/inotify.h>
#include <openssl/sha.h>

int main (int argc, char *argv[])
{
        int fd;
        int wd;
        unsigned char c[SHA512_DIGEST_LENGTH];
        int i;
        SHA512_CTX mdContext;
        int bytes;
        unsigned char data[1024];
        const int event_size = sizeof(struct inotify_event);
        const int buf_len = 1024 * (event_size + FILENAME_MAX);
        FILE *ftest;

        fd = inotify_init();

        if (fd < 0) {
          perror("inotify_init");
        }

        wd = inotify_add_watch(fd, "/home/joe/Documents", IN_CREATE);

        while (1) {
          char buff[buf_len];
          int no_of_events, count = 0;

          no_of_events = read (fd, buff, buf_len);
          while (count < no_of_events) {
            struct inotify_event *event = (struct inotify_event *)&buff[count];
            if (event->len) {
              if (event->mask & IN_CREATE)
              if(!(event->mask & IN_ISDIR)) {
                printf("The file %s has been created\n", event->name);

                ftest=fopen(event->name, "rb");  //segmentation fault 
                                                 //occurs here
                SHA512_Init (&mdContext);        
                while ((bytes = fread (data, 1, 1024, ftest)) != 0)
                    SHA512_Update (&mdContext, data, bytes);
                SHA512_Final (c,&mdContext);
                for(i = 0; i < SHA512_DIGEST_LENGTH; i++) printf("%02x", c[i]);
                printf (" %s\n", ftest);
                fclose (ftest);
                fflush(stdout);
              }
            }
            count += event_size + event->len;
          }
        }
        return 0;
}

Having ran this through Valgrind it does not provide any details of errors before the segmentation fault, and once the fault occurs does not provide details thereafter.

Upvotes: 1

Views: 557

Answers (1)

MK.
MK.

Reputation: 34517

You problem is that you are not checking any return values. Every function call that returns something must be checked and handled. In particular you are not checking return value of this:

ftest=fopen(event->name, "rb");  //segmentation fault 

if it returns null (e.g. because event->name contains file name, not full path and you are not running in the directory you are monitoring), you will get an error.

You are also not checking this

wd = inotify_add_watch(fd, "/home/joe/Documents", IN_CREATE);

and possibly others.

The other problem is that you are printing file handle as a string here:

printf (" %s\n", ftest);

Also in order to get useful information in debugger and in valgrind you need to build with debug info (gcc -g)

Upvotes: 3

Related Questions