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

Mustapha picture Mustapha · Dec 25, 2013 · Viewed 7.7k times · Source

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.

Answer

Jongware picture Jongware · Dec 25, 2013

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);
}