Skip to content

Commit

Permalink
SO 0512-5919: Use dirfd() too
Browse files Browse the repository at this point in the history
  • Loading branch information
jleffler committed Mar 2, 2020
1 parent 49d3c24 commit 0d7ef28
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 28 deletions.
6 changes: 6 additions & 0 deletions src/so-0512-5919/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,9 @@

[SO 0512-5919](https://stackoverflow.com/q/05125919) —
stat() error 'No such file or directory' when file name is returned by readdir()

Demonstrating the use of POSIX 2008 functions:

* `dirfd()` — get the file descriptor for a directory stream
* `fstatat()` — get stat information without needing chdir or string concatenation

47 changes: 19 additions & 28 deletions src/so-0512-5919/test-fstatat.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/* SO 5125919 */
#define _XOPEN_SOURCE 700
/* SO 0512-5919 */
#define _XOPEN_SOURCE 700 /* POSIX 2008 plus ... */
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
Expand All @@ -19,41 +18,33 @@ int main(int argc, char **argv)

for (int i = 1; i < argc; i++)
{
DIR *dp;
struct dirent *dirp;
struct stat sb;
int dfd = open(argv[i], O_RDONLY);
if (dfd == -1)
{
fprintf(stderr, "Failed to open directory %s for reading (%d: %s)\n",
argv[i], errno, strerror(errno));
continue;
}
if (fstat(dfd, &sb) != 0 || !S_ISDIR(sb.st_mode))
{
errno = ENOTDIR;
fprintf(stderr, "%s: %d %s\n", argv[i], errno, strerror(errno));
continue;
}
const char *name = argv[i];

if ((dp = opendir(argv[i]))==NULL)
DIR *dp = opendir(name);
if (dp == NULL)
{
perror("can't open dir");
continue;
fprintf(stderr, "failed to open directory %s (%d: %s)\n",
name, errno, strerror(errno));
return -1;
}
printf("%-20s %s\n", "Directory:", argv[i]);

int dfd = dirfd(dp); /* Very, very unlikely to fail */

printf("%-20s %s\n", "Directory:", name);

struct dirent *dirp;
while ((dirp = readdir(dp)) != NULL)
{
struct stat sb;
if (fstatat(dfd, dirp->d_name, &sb, 0) == -1) {
fprintf(stderr, "fstatat(\"%s\") failed (%d: %s)\n",
dirp->d_name, errno, strerror(errno));
continue;
fprintf(stderr, "fstatat(\"%s/%s\") failed (%d: %s)\n",
name, dirp->d_name, errno, strerror(errno));
}
printf("%-20s %s\n", "File name:", dirp->d_name);
else
printf("%-20s %s/%s\n", "File name:", name, dirp->d_name);
}

closedir(dp);
close(dfd);
}
return 0;
}

0 comments on commit 0d7ef28

Please sign in to comment.