I have a library that uses fstatat
to open a directory, and then stat a path relative to that directory using code resembling the following:
int fd = open("/some/directory", O_DIRECTORY);
if (-1 == fd) {
return;
}
struct stat st = {0};
if (-1 == fstatat(fd, "./file_in_dir", &st, AT_SYMLINK_NOFOLLOW)) {
}
close(fd);
I am able to enumerate the contents of the directory using fdopendir
/ readdir
, so I know I have a valid directory file descriptor. Regardless, no matter what I try, I always get a -1 return value from fstatat
(and openat
) with errno == EINVAL
(22).
According to the IBM documentation, fstatat
can result in EINVAL
when the flags are invalid. Having discovered this, I grepped the system headers for AT_SYMLINK_NOFOLLOW
and found the following:
#if (_XOPEN_SOURCE >= 700) || defined(_KERNEL)
#define AT_FDCWD (-2)
#define AT_EACCESS 1
#define AT_SYMLINK_NOFOLLOW 1
#define AT_SYMLINK_FOLLOW 2
#define AT_REMOVEDIR 1
#endif
Now, I may be off-base, but doesn't this seem like no matter what value you pass for flags, it is invalid because AT_REMOVEDIR
is the same value as AT_EACCESS
and AT_SYMLINK_NOFOLLOW
? Even if that isn't the case, I still haven't made it work.
I have tried every permutation of flags, trailing slashes, no trailing slashes, dot-slash prefix, no dot-slash prefix, etc. This code works correctly on every single platform we've encountered to date, and that is not an insignificant number.
I have been trying to figure this out for many hours now, so I am resorting to asking here. Anyone out there have a clue?
------------------------------
Jeff Johnson
------------------------------