I want to check whether given arguments are directory or not by using stat
. The program takes 2 argument: when first arguments is not directory or it does not exist code works correctly.
But when first argument is a directory and exists, and the second argument does not exist, the program says both of them exist -- wrong result. I would like to know why it does not work.
#include <stdio.h>
#include <sys/stat.h>
int main(int n, char **argv)
{
char *dir_1=argv[1], *dir_2=argv[2];
if (is_dir(dir_1) == 0)
printf("Directory %s exists.\n", dir_1);
else
printf("Directory %s does not exist.\n", dir_1);
if (is_dir(dir_2) == 0)
printf("Directory %s exists.\n", dir_2);
else
printf("Directory %s does not exist.\n", dir_2);
}
int is_dir(char *file)
{
struct stat file_stat;
stat(file, &file_stat);
return( (S_ISDIR(file_stat.st_mode)) ? 0 : -1);
}
If the file does not exist, stat
itself returns -1
, and sets errno
to ENOENT
. But since the first directory existed and was a directory, the struct stat
was filled with the information of a directory; this happens to be located at the exact same location in the stack for the second stat
invocation. The second stat
failed with the errno
ENOENT
, but then is_dir
interpreted the values left by the first invocation.
More correct implementation for the is_dir
could be:
int is_dir(char *file)
{
struct stat file_stat;
// if an error occurs, we return 0 for false
if (stat(file, &file_stat) < 0) {
return 0;
}
// otherwise we return whatever the S_ISDIR returns
return S_ISDIR(file_stat.st_mode);
}
Notice that I change the return value too; a function such as is_dir
is expected to return a boolean value that is truish (non-zero) in the case of the function name stating a true fact, zero otherwise.
You'd use it like:
if (is_dir(dir_1)) {
printf("Directory %s exists.\n", dir_1);
}
else {
printf("Directory %s does not exist.\n", dir_1);
}
if (is_dir(dir_2)) {
printf("Directory %s exists.\n", dir_2);
}
else {
printf("Directory %s does not exist.\n", dir_2);
}
Note that the return value 0 in this case does not mean that there necessarily is no directory with that name; the stat
system call could fail also because of insufficient permissions and so on; extending the logic (interpreting the value of errno
) is beyond the scope of this answer.