1

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.

Luqmaan
  • 2,052
  • 27
  • 34
Mustapha
  • 167
  • 1
  • 3
  • 11
  • 1
    And what would the *actual* permissions be? – Some programmer dude Dec 25 '13 at 18:51
  • Hi, they are the same for the three files: -rw-rw-r-- – Mustapha Dec 25 '13 at 18:52
  • 2
    You are requesting the `stat` of a file in your current working directory, not the one in your `midir`. If you checked the return value of `stat`, you'd have noticed that. (Oh, and so `fileStat` is not modified so you get the same "result" over and over again.) – Jongware Dec 25 '13 at 20:52
  • @Jongware thanks for replying what argument should i pass to stat to correct that?, thanks again. – Mustapha Dec 25 '13 at 21:07
  • It's been a while since I've used permission modes in C, but I think you need to fix the comparison operator: `( fileStat.st_mode & S_IRUSR ) == S_IRUSR`, etc... – millinon Dec 25 '13 at 21:56
  • @Jongware thanks a lot i get it know, i accept your answer as the best answer, one more thing can you help me with another problem?, i want to walk through a directory in depth walking all subdirectories? i appreciate it. – Mustapha Dec 25 '13 at 22:02
  • @Mustapha: that is a new question. As always, you need to start by showing what you got so far. – Jongware Dec 25 '13 at 22:03
  • @millinon: no, the mode bits are all single bits. Also see this (remarkably alike) question: http://stackoverflow.com/questions/10323060/printing-file-permissions-like-ls-l-using-stat2-in-c – Jongware Dec 25 '13 at 22:04
  • My mistake, I was thinking of XORing them or something. Thanks for the correction. – millinon Dec 25 '13 at 22:06

1 Answers1

2

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);
}
Jongware
  • 22,200
  • 8
  • 54
  • 100