0

I'm currently working on a 4 part project, the last part of which is to recursively list the names of all files in a directory tree. The program works fine if run from the cwd but when I try to pass in a directory as a command line argument the program won't open any subdirectories, it just prints the name. I've tested and narrowed the issue down (I think) to the S_ISDIR call not returning true if I'm not in the cwd but I really don't see why it would do that. I'm actually having a similar problem with another part of the project so I don't know if I'm just misunderstanding directory traversal or what. Any help would be greatly appreciated. Thanks! This is what I have so far for the function:

void recursiveSearch(char* dir){
    DIR* cur = opendir(dir);
    assert(cur != NULL);
    struct dirent* d;
    struct stat* s = malloc(sizeof(struct stat));

    while((d = readdir(cur)) != NULL){

        if((strcmp(d->d_name, ".") == 0) || (strcmp(d->d_name, "..") == 0))
            continue;

        stat(d->d_name, s);
        if(S_ISDIR(s->st_mode))
            recursiveSearch(d->d_name);

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

    }
    closedir(cur);

    return;
}

Here's my not-so-elegant solution after getting advice:

while((d = readdir(cur)) != NULL){

    if((strcmp(d->d_name, ".") == 0) || (strcmp(d->d_name, "..") == 0))
        continue;

    char* buf = malloc(sizeof(char) * BUFSIZ);
    buf = realpath(dir, buf);
    strcat(buf, "/");
    strcat(buf, d->d_name);

    stat(buf, s);
    if(S_ISDIR(s->st_mode))
        recursiveSearch(buf);

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

}
  • The basic problem is that the name returned by `readdir()` is relative to the the directory, so to work down a hierarchy, you have to prefix the name returned with the name of the directory containing it — which your code doesn't do. You could also use POSIX [`nftw()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/nftw.html), and you might find the `*at()` functions such as [`statat()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/statat.html) and [`dirfd()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/dirfd.html) of use too. – Jonathan Leffler Apr 25 '20 at 16:08
  • See also [`stat()` giving wrong information](https://stackoverflow.com/a/60492801/15168) — and no doubt there are other Q&A on the topic too. – Jonathan Leffler Apr 25 '20 at 16:16
  • Thank you very, very much, Jonathan. Your advice pointed me in the right direction. My solution isn't very elegant but it works. That's good enough for me for the time being, I can look deeper into it later. Thanks again. – Timothy O'Rourke Apr 25 '20 at 17:18
  • Looks about right, though it's hard to read code in a comment (don't leave a space between the opening back-tick and the first character of the code; spaces don't work). Using `realpath()` is a fairly heavy-weight solution, but should do the job. – Jonathan Leffler Apr 25 '20 at 17:22

0 Answers0