I wrote a "recursive" readdir function but if I want to check the files in a subdirectory errno is set to ENOENT. If it finds a directory, the directory name is given to the function and printing DIR->d_name gives me the fullpath to the subdirectory. I could not figure it out why this is happening. I wrote this function an it works (for the first subdirectory) but I think checking for stat will fail in a subdir of a subdir too. Has this something to do with recursion?
!!!SOLUTION BELOW CODE!!!
Here is my code: (Probably a bad Error handler but I dont know better yet. Still learning.)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
DIR *Directory_Error_Handler(DIR *directory_return)
{
//const char[] = "dirname";
if(directory_return == 0){
switch(errno){
case EACCES: printf("Permission denied.\n"); return 0;
case EBADF: printf("Not a valid files descriptor opened for reading.\n"); return 0;
case EMFILE: printf("The per-process limit on the number of open file descriptors has been reached.\n"); return 0;
case ENFILE: printf("The system-wide limit on the total number of open files has been reached.\n"); return 0;
case ENOENT: printf("Directory does not exist, or name is an empty string.\n"); return 0;
case ENOMEM: printf("Insufficient memory to complete the operation.\n"); return 0;
case ENOTDIR: printf("'name' is not a directory.\n"); return 0;
default: return directory_return;
}
}
return directory_return;
}
int Stat_Error_Handler(const char *path, struct stat* file_info)
{
if(stat(path, file_info)){
switch (errno)
{
case EACCES: printf("Search permission is denied for one of the directories in the path prefix of pathname.\n"); return -1;
case EBADF: printf("fd is not a valid open file descriptor.\n"); return -1;
case EFAULT: printf("Bad address.\n"); return -1;
case EINVAL: printf("fstatat() Invalid flag specified.\n"); return -1;
case ELOOP: printf("Too many symbolic links encountered while traversing the path.\n"); return -1;
case ENAMETOOLONG: printf("pathname is too long.\n"); return -1;
case ENOENT: printf("A component of pathname does not exist or is a dangling symbolic link. or pathname is an empty string and AT_EMPTY_PATH was not specified in flags.\n"); return -1;
case ENOMEM: printf("Out of memory.\n"); return -1;
case ENOTDIR: printf("A component of the path prefix of pathname is not a directory.\n"); return -1;
case EOVERFLOW: printf("pathname or fd refers to a file whose size, inode number,\n \
or number of blocks cannot be represented in,\n \
respectively, the types off_t, ino_t, or blkcnt_t. This\n \
error can occur when, for example, an application compiled\n \
on a 32-bit platform without -D_FILE_OFFSET_BITS=64 calls\n \
stat() on a file whose size exceeds (1<<31)-1 bytes.\n"); return -1;
default: return 0;
}
}
return 0;
}
void walk(DIR *root_directory)
{
struct dirent *dir_entry;
struct stat file_info;
printf("Directory: %s\n", root_directory->dd_name);
while((dir_entry = readdir(root_directory)) != NULL) {
if(Stat_Error_Handler(dir_entry->d_name, &file_info) != 0){
continue;
}
if(S_ISDIR(file_info.st_mode)){
if(dir_entry->d_name[0] == '.' || (dir_entry->d_name[0] == dir_entry->d_name[1]))
continue;
walk(Directory_Error_Handler(opendir(dir_entry->d_name)));
}
printf("\t-> %s\n", dir_entry->d_name);
}
closedir(root_directory);
}
int main(void)
{
walk(Directory_Error_Handler(opendir(".")));
return 0;
}
Solution: with help from this posts first answer
Replaced the hardcoded **** with strerror(). Thx to zwol.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <errno.h>
DIR *Directory_Error_Handler(DIR *directory_return)
{
//const char[] = "dirname";
if(directory_return == 0){
printf("%s\n", strerror(errno));
}
return directory_return;
}
int Stat_Error_Handler(const char *path, struct stat* file_info)
{
if(stat(path, file_info) != 0){
printf("%s\n", strerror(errno));
return -1;
}
return 0;
}
void walk(DIR *root_directory)
{
struct dirent *dir_entry;
struct stat file_info;
char *EndPtr;
char Path[256] = {0}; EndPtr = Path;
strncpy(Path, root_directory->dd_name, strlen(root_directory->dd_name)-1); // because i get a * after the last /
EndPtr += strlen(Path);
while((dir_entry = readdir(root_directory)) != NULL) {
strcpy(EndPtr, dir_entry->d_name);
if(Stat_Error_Handler(Path, &file_info) != 0){ // give the fullpath to stat()
continue;
}
if(S_ISDIR(file_info.st_mode)){
if(dir_entry->d_name[0] == '.' || (dir_entry->d_name[0] == dir_entry->d_name[1]))
continue;
walk(Directory_Error_Handler(opendir(Path))); // replaceing the dir_entry->d_name with Path
} else // <-
printf("\t-> %s\n", Path); // putting this into else because i only need filenames
}
closedir(root_directory);
}
int main(void)
{
walk(Directory_Error_Handler(opendir(".")));
return 0;
}