Search code examples
cdirectorystat

Problem reading directories in C


I am writing a simple C program that receives a directory as an argument and displays the files in this directory and also his subdirectories. I wrote a "recursive" function for doing that. But for an unknown reason, my program fails at the stat function. Here is my program :

    #define _POSIX_SOURCE 1

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>


void display_directory(char* path){

  DIR* directory = opendir(path);
  if( directory == NULL){
    printf("opendir failure for %s\n", path);
    exit(1);
  }


 struct dirent* dirent;
 struct stat stat_info;

 while((dirent = readdir(directory)) != NULL){
   printf("[%s]\n", dirent->d_name);
   if(stat(dirent -> d_name, &stat_info) == -1){
     printf("readdir error for %s\n", dirent->d_name);
     exit(1);
   }
   if(S_ISREG(stat_info.st_mode)){
       printf("File: %s \n", dirent -> d_name); 
   }
   if(S_ISDIR(stat_info.st_mode)){
     if(strncmp(dirent->d_name, "..",2)){
       printf("Directory : %s\n", dirent->d_name);
       display_directory(dirent->d_name);
     }  
    }

 }

 closedir(directory);
}

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

char* path;

if(argc > 1){
 path = argv[1];
} else {
 path = ".";
}

display_directory(path);

 return EXIT_SUCCESS;
}

For instance, if in my directory A, I have a1, a2, a3 and .., it reads first the .. directory, and when it reads the directory a1, the stat function fails.

Can someone tells me what is not correct with my code.

[EDIT] I included <errno.h> as many of you suggest and after running the program, I have the error Too many open files.

    #define _POSIX_SOURCE 1

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>


void display_directory(char* path){

  DIR* directory = opendir(path);
  if( directory == NULL){
    printf("opendir failure for %s --> %s\n", path, strerror(errno));
    exit(1);
  }


 struct dirent* dirent;
 struct stat stat_info;

 while((dirent = readdir(directory)) != NULL){
   printf("[%s]\n", dirent->d_name);
   if(stat(dirent->d_name, &stat_info)){
     printf("readdir error for %s ---> %s\n", dirent->d_name, strerror(errno));
     continue;
   }
   if(S_ISREG(stat_info.st_mode)){
       printf("Fichier : %s \n", dirent->d_name); 
   }
   if(S_ISDIR(stat_info.st_mode)){
     if(strncmp(dirent->d_name, "..",2)){
       printf("Directory : %s\n", dirent->d_name);
       display_directory(dirent->d_name);
     }  
    }

 }

 closedir(directory);
}

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

char* path;

if (argc > 2) { 
 fprintf(stderr, "Usage: %s [directory]\n", argv[0]); 
 exit(1); 
}

path = argv[1];


display_directory(path);

 return EXIT_SUCCESS;
}

The output of the program :

[..]
[mykill.c]
readdir error for mykill.c ---> No such file or directory
[.]
Directory : .
[..]
[.]
Directory : .
[..]
[.]
Directory : .
[..]

...
...
Directory : .
opendir failure for . --> Too many open files

mykill.c is a file in the directory that was passed as an argument.


Solution

  • if(S_ISDIR(stat_info.st_mode)){
     if( !strcmp(dirent->d_name, ".")) continue;
     if( !strcmp(dirent->d_name, "..")) continue;
    
     printf("Directory : %s\n", dirent->d_name);
     display_directory(dirent->d_name);
    }