0

I am writing a simple c program which outputs all the contents within a given directory. Files are printed in green, executables are printed in red, and directories are printed in blue. Files and executables have their size printed as well. The code works properly when I open the current directory with either a relative path (".") or an absolute path. However, when I open other directories, all contents are identified as directories and printed in blue. I am unsure why the behavior changes when opening different directories.

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

int main(int argc, char *argv[]){
    DIR* dir;
    struct dirent* sd;
    
    dir = opendir(".");

    if(dir == NULL){
        exit(1);
    }
    int fd;
    int size;
    while((sd=readdir(dir)) != NULL){
        struct stat statstruct;
        stat(sd->d_name, &statstruct);
        
        if(S_ISREG(statstruct.st_mode)){
            fd = open(sd->d_name, O_RDONLY);
            size = lseek(fd, 0, SEEK_END);
            if(statstruct.st_mode & S_IXUSR){
                printf("\033[1;31m%s %d bytes\n\033[0m", sd->d_name, size);
            }
            else{
                printf("\033[0;32m%s %d bytes\n\033[0m", sd->d_name, size);
            }
            
        }
        else if(S_ISDIR(statstruct.st_mode)){
            printf("\033[0;34m./%s\n\033[0m", sd->d_name);
        }
        
        
    }

    closedir(dir);

}
abnj77
  • 1
  • 1
  • *When I open other directories*. What other directories specifically? You mean a relative directory? Or do you mean the subdirectories of the directory the program starts off in? Please clarify. – kaylum Nov 24 '20 at 20:09
  • 1
    `stat(sd->d_name,` that path is relative. Pass there a full path. – KamilCuk Nov 24 '20 at 20:13
  • 1
    Also, check the return value of stat(). This would have tipped you off to the fact that it was returning ENOENT and would've led you to inspect the path you were passing to readdir() – Thomas Kammeyer Nov 24 '20 at 20:18
  • You need to check the return value from `stat()`, which will be telling you `ENOENT`. The duplicate question explains how to work around these issues. – Jonathan Leffler Nov 24 '20 at 20:42

1 Answers1

1
stat(sd->d_name, &statstruct);

stat opens relative to current directory. So the file will be parsed relative to current directory. Instead open the file relative to the directory you are interested in.

int err = fstatat(dirfd(dir), sd->d_name, &statstruct, 0);
if (err) abort(); // yes, handle errors
KamilCuk
  • 120,984
  • 8
  • 59
  • 111