sys/stat S_ISDIR(m) with struct dirent
-
04-06-2021 - |
Вопрос
I want to check to see if a file is a directory, link, or just a regular file. I loop through the directory and save each file as struct dirent *
. I try to pass d_ino
to S_ISDIR(m)
, S_ISLINK(m)
, or S_ISREG(m)
and regardless of the file, I will not get a positive result. So my question is: how do I use S_ISDIR(m)
with struct dirent
?
Решение
When you read a directory using readdir(3)
, the file type is stored in the d_type
member variable of each struct dirent
you receive, not the d_ino
member. You rarely will care about the inode number.
However, not all implementations will have valid data for the d_type
member, so you may need to call stat(3)
or lstat(3)
on each file to determine its file type (use lstat
if you're interested in symbolic links, or use stat
if you're interested in the targets of symbolic links) and then examine the st_mode
member using the S_IS***
macros.
A typical directory iteration might look like this:
// Error checking omitted for expository purposes
DIR *dir = opendir(dir_to_read);
struct dirent *entry;
while((entry = readdir(dir)) != NULL)
{
struct stat st;
char filename[512];
snprintf(filename, sizeof(filename), "%s/%s", dir_to_read, entry->d_name);
lstat(filename, &st);
if(S_ISDIR(st.st_mode))
{
// This directory entry is another directory
}
else if(S_ISLINK(st.st_mode))
{
// This entry is a symbolic link
}
else if(S_ISREG(st.st_mode))
{
// This entry is a regular file
}
// etc.
}
closedir(dir);
Другие советы
S_ISDIR(m), S_ISLINK(m) is to be used against struct stat.st_mode
, and not struct dirent
. eg:
struct stat sb;
...
stat ("/", &sb);
printf ("%d", S_ISDIR (sb.st_mode));
Unfortunately you cannot use the S_IS* macros with struct dirent members, as stated above. However you don't need to since the member d_type already has that info for you. You can directly test it like this:
struct dirent someDirEnt;
... //stuff get it filled out
if(someDirEnt.d_type==DT_LNK)
...//whatever you link
In particular the d_type member may contain:
DT_BLK This is a block device. DT_CHR This is a character device. DT_DIR This is a directory. DT_FIFO This is a named pipe (FIFO). DT_LNK This is a symbolic link. DT_REG This is a regular file. DT_SOCK This is a UNIX domain socket. DT_UNKNOWN The file type is unknown.