Search code examples
cstatreaddiropendir

How to walk through a directory in c and print all files name and permissions


Hello i want to make a program in c that recieves the name of a directory as an argument, show all files in it and their permissions in rwx format, here's the code:

DIR* midir;
if ((midir=opendir(argv[1])) < 0) {
    perror("\nError en opendir\n");
    exit(-1);
}
struct dirent* info_archivo;
struct stat fileStat;

while ((info_archivo = readdir(midir)) != NULL) {
    stat(info_archivo->d_name, &fileStat);
    printf((S_ISDIR(fileStat.st_mode))  ? "d" : "-");
    printf((fileStat.st_mode & S_IRUSR) ? "r" : "-");
    printf((fileStat.st_mode & S_IWUSR) ? "w" : "-");
    printf((fileStat.st_mode & S_IXUSR) ? "x" : "-");
    printf((fileStat.st_mode & S_IRGRP) ? "r" : "-");
    printf((fileStat.st_mode & S_IWGRP) ? "w" : "-");
    printf((fileStat.st_mode & S_IXGRP) ? "x" : "-");
    printf((fileStat.st_mode & S_IROTH) ? "r" : "-");
    printf((fileStat.st_mode & S_IWOTH) ? "w" : "-");
    printf((fileStat.st_mode & S_IXOTH) ? "x" : "-");
    printf("\n\n");
}
closedir(midir);

the output is wrong it gets the files name right but the permissions wrong:

..: permissions: drwxr-xr-x

file1: permissions: drwxr-xr-x

file3: permissons: drwxr-xr-x

.: permissions: drwxr-xr-x

file2: permissions: drwxr-xr-x

Help is appreciated.


Solution

  • You are requesting the stat of the files in your current working directory, not the ones in your midir -- and the calls fail because the files you request a stat on do not exist in there. If you checked the return value of stat, you'd have noticed that, since it returns 0 on success. As it is, fileStat is not modified in case of an error, and you get the same "result" over and over again.

    Since the file you request a stat for may be outside the current working directory, you need to add its full path. Assuming 256 bytes is long enough for your paths, and your path delimiter is /, the following approach should work.

    #include <stdio.h>
    #include <stdlib.h>
    #include <dirent.h>
    #include <err.h>
    #include <sys/stat.h>
    #include <string.h>
    
    int main (int argc, char **argv)
    {
        DIR *midir;
        struct dirent* info_archivo;
        struct stat fileStat;
        char fullpath[256];
    
        if (argc != 2)
        {
            perror("Please supply a folder name\n");
            exit(-1);
        }
    
        if ((midir=opendir(argv[1])) == NULL)
        {
            perror("Error in opendir");
            exit(-1);
        }
    
        while ((info_archivo = readdir(midir)) != 0)
        {
            printf ("%s ", info_archivo->d_name);
            strcpy (fullpath, argv[1]);
            strcat (fullpath, "/");
            strcat (fullpath, info_archivo->d_name);
            if (!stat(fullpath, &fileStat))
            {
                printf((S_ISDIR(fileStat.st_mode))  ? "d" : "-");
                printf((fileStat.st_mode & S_IRUSR) ? "r" : "-");
                printf((fileStat.st_mode & S_IWUSR) ? "w" : "-");
                printf((fileStat.st_mode & S_IXUSR) ? "x" : "-");
                printf((fileStat.st_mode & S_IRGRP) ? "r" : "-");
                printf((fileStat.st_mode & S_IWGRP) ? "w" : "-");
                printf((fileStat.st_mode & S_IXGRP) ? "x" : "-");
                printf((fileStat.st_mode & S_IROTH) ? "r" : "-");
                printf((fileStat.st_mode & S_IWOTH) ? "w" : "-");
                printf((fileStat.st_mode & S_IXOTH) ? "x" : "-");
            } else
            {
                perror("Error in stat");
            }
            printf("\n");
        }
        closedir(midir);
    }