Search code examples
cunixsegmentation-faultdirent.h

How to fix segmentation fault in the use of struct dirent in C


My code prints the files/directory names in a given path(user enters it as a command-line argument). When executing with a given path in the directory, it just works fine but it is supposed to do the same for the current working directory if user does not provide any command-line argument.

I am getting seg fault if I just run as: ./a.out
It works when I run as: ./a.out /path

Please fix my code by providing the necessary code fragment

I have tried to do debugging and found out that it gives the error right after it executes the line following line in the depthFirst function

printf("%s\n", sd->d_name);

My faulty code:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <limits.h>
void depthFirst(char * path){
        struct dirent *sd;
        DIR *dir;
        //char path[PATH_MAX];

        dir = opendir(path);


                if(dir == NULL){
                        printf("Error, unable to open\n");
                        exit(1);
                }

                while( (sd = readdir(dir)) != NULL){
                        if(strcmp(sd->d_name, ".") != 0 && strcmp(sd->d_name, "..") != 0){
                        printf("%s\n", sd->d_name);
                        realpath(sd->d_name,path);
                        if(isdirectory(path)){
                                printf("\t");
                                depthFirst(sd->d_name);

                        }
                }

                }


        closedir(dir);
}

int isdirectory(char *path) {
   struct stat statbuf;
   if (stat(path, &statbuf) == -1)
      return 0;
   else
      return S_ISDIR(statbuf.st_mode);
}

int main(int argc, char *argv[]){
        char * path;
        char * currentDirectory;

        if(argc<2){
                currentDirectory = ".";
                depthFirst(currentDirectory);
        }
        else{
                path = argv[1];
                depthFirst(path);

        }
        return 0;
}

The output is shown below:

.git
Segmentation fault

Solution

  • Jonathan beat me to it in the comments, but this change prevents the problem.

    @@ -9,7 +9,7 @@
     void depthFirst(char * path){
             struct dirent *sd;
             DIR *dir;
    -        //char path[PATH_MAX];
    +        char rpath[PATH_MAX];
    
             dir = opendir(path);
    
    @@ -22,8 +22,8 @@
                     while( (sd = readdir(dir)) != NULL){
                             if(strcmp(sd->d_name, ".") != 0 && strcmp(sd->d_name, "..") != 0){
                             printf("%s\n", sd->d_name);
    -                        realpath(sd->d_name,path);
    -                        if(isdirectory(path)){
    +                        realpath(sd->d_name,rpath);
    +                        if(isdirectory(rpath)){
                                     printf("\t");
                                     depthFirst(sd->d_name);
    
    

    As another comment pointed out, you cannot reuse the char* path because it is stored in a page of memory that is not writable by your program. Therefore, realpath() will crash upon attempting to write to it.