John Vulconshinz
John Vulconshinz

Reputation: 1148

Incorrect st_mode Values - C

Update: I have solved the problem by using chdir() to change the current working directory before I call opendir(). So I am assuming that opendir() can only open a directory that is in the current working directory. So my new question is, am I correct?

I am currently writing a basic imitation of window's dir command. My program works properly when the "." wildcard is used as an argument for opendir(). But when I don't use the wildcard and specify a directory instead. My program will not open the directory specified to it. For example if I type c:\windows it will open c:\ instead and each file's st_mode will be the same. At least I assume that they are all the same because all of the file types(DIR, FILE, OTHER) are the same.

#include <stdio.h>
#include <string.h>

#include <sys/stat.h>
#include <dirent.h>

int main(int argc, char* argv[])
{
//'directory' points to the directory | 'directory_contents' is used with readdir() to read the directory's('directory') contents.
DIR *directory;
struct dirent *directory_contents;
struct stat file_info;

//IF no argument is present display the contents of the current directory | IF there is an arugment display the contents of that argument | ELSE Too many arguments
if (argc == 1)
{
    directory = opendir(".");
}
else if (argc == 2)
{
    //New Code
    chdir(argv[1]); directory = opendir(".");

    //Old Code
    directory = opendir(argv[1]);
}
else
{
    printf("ERROR: Extra arguments\n");
}

//Checks to see if the directory opened above was actually opened.
if (directory == NULL)
{
    printf("ERROR: Failed to open '%s'.\n", argv[1]);
    return 2;
}
else
{
    //WHILE there are file names to be read THEN read the file names
    while (directory_contents = readdir(directory))
    {
        stat(directory_contents->d_name, &file_info);

        //Test for directory
        if(S_ISDIR(file_info.st_mode))
        {
            //File type
            printf("<DIR>   ");

            //File name
            if(strlen(directory_contents->d_name) <= 15)
            {
                printf("%-15s", directory_contents->d_name);
            }
            else if(strlen(directory_contents->d_name) > 15)
            {
                printf("%.12s.. ", directory_contents->d_name);
            }

            //File premissions
            printf("<%c%c%c>\n", ((file_info.st_mode & S_IRUSR)==0) ? '-' : 'r', ((file_info.st_mode & S_IWUSR)==0) ? '-' : 'w', ((file_info.st_mode & S_IXUSR)==0) ? '-' : 'x');
        }
        //Test for a regular file.
        else if(S_ISREG(file_info.st_mode))
        {
            //File type
            printf("<FILE>  ");

            //File name
            if(strlen(directory_contents->d_name) <= 15)
            {
                printf("%-15s", directory_contents->d_name);
            }
            else if(strlen(directory_contents->d_name) > 15)
            {
                printf("%.12s.. ", directory_contents->d_name);
            }

            //File premissions
            printf("<%c%c%c> ", ((file_info.st_mode & S_IRUSR)==0) ? '-' : 'r', ((file_info.st_mode & S_IWUSR)==0) ? '-' : 'w', ((file_info.st_mode & S_IXUSR)==0) ? '-' : 'x');

            //File size
            if (file_info.st_size < 1000)
            {
                printf("<%-3i B>\n", file_info.st_size);
            }
            else if ( (file_info.st_size > 1000) && (file_info.st_size < 1000000) )
            {
                printf("<%-3i KB>\n", file_info.st_size/1000);
            }
            else if ( (file_info.st_size > 1000000) && (file_info.st_size < 1000000000) )
            {
                printf("<%-3i MB>\n", file_info.st_size/1000000);
            }
            else
            {
                printf("<%-3i GB>\n", file_info.st_size/1000000000);
            }
        }
        //Symbolic Link etc.
        else
        {
            //File type
            printf("<OTHER> ");

            //File name
            if(strlen(directory_contents->d_name) <= 15)
            {
                printf("%-15s", directory_contents->d_name);
            }
            else if(strlen(directory_contents->d_name) > 15)
            {
                printf("%.12s.. ", directory_contents->d_name);
            }

            //File premissions
            printf("<%c%c%c>\n", ((file_info.st_mode & S_IRUSR)==0) ? '-' : 'r', ((file_info.st_mode & S_IWUSR)==0) ? '-' : 'w', ((file_info.st_mode & S_IXUSR)==0) ? '-' : 'x');
        }
    }
}
}

And yes I do know that the permissions I am outputting are completely irrelevant because of Window's use of ACLs. I am only writing this program on windows because I have no choice right now but it is intended for a Linux OS.

Upvotes: 0

Views: 1467

Answers (1)

Armin Rigo
Armin Rigo

Reputation: 12900

stat(directory_contents->d_name,

This line is the problem. The d_name field is just the name of the file without any directory. So unless the directory happens to be the current directory, the call to stat() will not find the file.

Upvotes: 1

Related Questions