Reputation: 1
I am trying to open a directory and read the files and folders and add '/' at the end of if it is a folder. This is my current code.
#include <dirent.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int isDir(const char* target)
{
struct stat statbuf;
stat(target, &statbuf);
return S_ISDIR(statbuf.st_mode);
}
int main(int argc, char * argv[])
{
puts("");
struct stat sfile;
struct dirent *dp;
char * dir;
if(argc != 2)
dir = getenv("PWD"); //default
else
dir = argv[1];
DIR *dirp = opendir(dir);
dp = readdir(dirp);
while ( dp != NULL )
{
stat(dp->d_name,&sfile);
//opendir(dp->d_name);
printf("Size : %ld ",sfile.st_size);
if (isDir(dp->d_name))
{
printf("%s/\n",dp->d_name);
}
else
{
printf("%s \n",dp->d_name);
}
dp = readdir(dirp);
}
printf("\n");
closedir(dirp);
}
This works when I pass no arguments, ie, it is reading files and folders in the current working directory. When I pass a directory as argument, it fails to detect further folders in that as directories. Curiously, when tried using errno when I try to open using opendir(), all the contents are detected as directories.
int isDir2(const char* target)
{
opendir(target);
if(errno == ENOTDIR)
{
puts("Not directory");
return 0;
}
else
{
puts("Directory"); //only this is getting printed
return 1;
}
}
In either case, when both '.' and '..' are detected as directories but the rest as either directories or files depending on whether I am using opendir()'s errno or S_ISDIR.
Upvotes: 0
Views: 164
Reputation: 1
So the issue was of working directories. When I checked what the stat function in the isDir() function was returning, it was returning -1. It wasn't able to find the file/folder because it's current working directory was not the folder it was given, rather the cwd where the program was run. What I did was change the directory to the given folder and it works.
The code now:
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
int isDir(const char* target)
{
struct stat statbuf = {0};
int result = 0;
int err = stat(target, &statbuf);
if (err != -1)
{
result = S_ISDIR(statbuf.st_mode);
}
return result;
}
int main(int argc, char * argv[])
{
puts("");
struct stat sfile;
struct dirent *dp;
char * dir;
if(argc != 2)
dir = getenv("PWD"); //default
else
dir = argv[1];
DIR *dirp = opendir(dir);
dp = readdir(dirp);
chdir(dir);
while ( dp != NULL )
{
stat(dp->d_name,&sfile);
printf("Size : %ld ",sfile.st_size);
if (isDir(dp->d_name))
{
printf("%s/\n",dp->d_name);
}
else
{
printf("%s \n",dp->d_name);
}
dp = readdir(dirp);
}
printf("\n");
closedir(dirp);
}
Upvotes: 0
Reputation: 104474
Your isDir
function isn't actually checking the return value from stat
to validate that it succeeded. And since your statbuf
variable is uninitialized, it's undefined behavior.
Better:
int isDir(const char* target)
{
struct stat statbuf = {0};
int result = 0;
if (stat(target, &statbuf) != -1)
{
result = S_ISDIR(statbuf.st_mode);
}
return result;
}
Further, you are invoking opendir
without assigning it's return value:
while ( dp != NULL )
{
stat(dp->d_name,&sfile);
opendir(dp->d_name); // WHERE'S THE RESULT?
You need to rethink your logic in this while loop with regards to invoking opendir
, readdir
, and don't forget to invoke closedir
.
Upvotes: 1