Originally Posted by
t1497f35
I strongly suggest you
stop using dirent.d_type for checking the type of the file.
I just made this mistake in my app and had to rewrite it to use
stat instead.
That's because i.e. on XFS dirent.d_type is not supported because dirent
only guarantees that the filename (d_name) always be present.
Source:
http://www.gnu.org/s/libc/manual/htm...ectory-Entries
Researching this I found bugs on launchpad about apps because they've been relying on dirent.d_type and the solution was to switch over to stat.
I think this is good advice, use dirent to determine the filename, and then do a stat or lstat on the file. Something like this (in C, in C++ you could use a std::stringstream or std::string instead of namebuf/snprintf/etc):
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
static void list_dir(const char* base_dir)
{
DIR* dir;
struct dirent* ent;
struct stat buf;
char namebuf[PATH_MAX];
size_t base_len = strlen(base_dir);
if (!(dir = opendir(base_dir))) {
perror("failed to open directory");
return;
}
while((ent = readdir(dir)) != NULL) {
/* ignore .. and . */
if (!strcmp(ent->d_name, "..") || !strcmp(ent->d_name, ".")) {
continue;
}
snprintf(namebuf, sizeof(namebuf), "%s%s%s",
base_dir,
(base_dir[base_len - 1] == '/' ? "" : "/"),
ent->d_name);
if (lstat(namebuf, &buf) != 0) {
perror(namebuf);
continue;
}
if (S_ISREG(buf.st_mode)) {
printf("FILE: %s\n", namebuf);
} else if (S_ISLNK(buf.st_mode)) {
printf("LINK: %s\n", namebuf);
} else if (S_ISDIR(buf.st_mode)) {
printf("DIR: %s\n", namebuf);
/* recurse, if desired */
/* list_dir(namebuf); */
}
}
closedir(dir);
}
Bookmarks