0

my code is not working. I need to display all directories inside the directory given as the command line argument. So far I have tried this:

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

struct stat my_stat;

int searchDirectory (char *dirName);

int searchDirectory(char *dirName){
    struct dirent *pDirent;
    DIR *pDir;

    pDir = opendir(dirName);
    if (pDir == NULL) {
        printf("Cannot open directory '%s'\n", dirName );
        return 1;
    }

    while ((pDirent = readdir(pDir)) != NULL){
        printf("%s\n", pDirent->d_name);
        stat(pDirent->d_name, &my_stat);
        if (S_ISDIR(my_stat.st_mode)){
            searchDirectory(pDirent->d_name);
            printf("Directory Found: %s\n", pDirent->d_name);
        }
    }

    return 0;
}

int main(int argc, char *argv[]){
    struct stat my_stat;


    if (lstat(argv[1], &my_stat) < 0){
        perror("stat error");
    }

    if (S_ISDIR(my_stat.st_mode)){ 
        printf("Directory found\n");
        searchDirectory(argv[1]);
    }

    return 0;
}

I am not sure why but for some reason my code is reading normal files as a directory, but S_ISDIR(my_stat.st_mode)) should prevent this. Any idea on what could be wrong?

Erik L
  • 3
  • 1
  • And what is your output ? Did you do even basic printf debugging `? – Jabberwocky Apr 02 '16 at 15:40
  • 1
    This is a duplicate question — the difficulty, as ever, is finding the question it is a duplicate of. – Jonathan Leffler Apr 02 '16 at 15:53
  • @JonathanLeffler no problemo: Googling the exact title gives: 'About 511,000 results', with SO Q&A on teh first page. – Martin James Apr 02 '16 at 16:31
  • For instance: http://stackoverflow.com/questions/8436841/how-to-recursively-list-directories-in-c-on-linux – Martin James Apr 02 '16 at 16:33
  • For sure, I have answered at least one of these 'you need to concat the path and the folder name to do the recurse' thingies. – Martin James Apr 02 '16 at 16:35
  • @MartinJames: I looked at that ([SO 8436841](http://stackoverflow.com/q/8436841)) and it has two good answers (one using `opendir()` et al, one using `nftw()` instead). However, it isn't a question where the OP ran foul of the "must concatenate path and name read by `readdir()`" problem — it evades it from the start. OTOH, most of the questions where that was the problem are probably not highly up-voted. Fiddly. I may spend some more time looking later. I won't object if someone wields Mjölnir to close to what you suggest, but there may be a better choice. – Jonathan Leffler Apr 02 '16 at 17:05
  • 1
    You need to close the directory, too. For example, add `closedir( pDir );` after the `while()`-loop and before `return`. And as noted below, check the name isn't `"."` or `".."` or you will go into infinite recursion. – Andrew Henle Apr 02 '16 at 18:02

2 Answers2

2

The problem you are having is that pDirent->d_name is relative to the directory that you are currently listing while you process has a working directory of where you started the process.

To fix, concatename the names of the directory before doing the opendir

int searchDirectory(char *dirName){
    ......
    while ((pDirent = readdir(pDir)) != NULL){
        printf("%s\n", pDirent->d_name);
        stat(pDirent->d_name, &my_stat);
        if (S_ISDIR(my_stat.st_mode)){
            // construct new path ....
            char * dirname = malloc(strlen(dirName)+strlen(pDirent->d_name)+2);
            strcat(strcat(strcpy(dirname,dirName),"/"),pDirent->d_name);
            searchDirectory(dirname);
            free(dirname)
            printf("Directory Found: %s\n", pDirent->d_name);
        }
     }
     .....

Also note, that you need to handle the . and .. directories as special cases as your code otherwise will end up in an infinite recursion, so you need extra code to handle those -- see this question for details

Community
  • 1
  • 1
Soren
  • 14,402
  • 4
  • 41
  • 67
1

Your recursive call to searchDirectory(pDirent->d_name); is wrong because you got a name relative to directory you are parsing, so you need to concatenate both the name of the directory you are actually parsing and the relative (to that directory) name you got:

char newDir[PATH_MAX];
snprintf(newDir,PATH_MAX,"%s/%s",dirName,pDirent->d_name);
searchDirectory(newDir);
Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69