I have a short program to output a directory's files.
Why don't you use the proper interface for that,
scandir() or
nftw()?
If I open the current directory with opendir("."), it works fine. But if I specify a path, it will list the filenames correctly, but the attributes are wrong.
The
d_name field of a
struct dirent only contains the file name part.
When you do
DIR *dir = opendir("/home/myself/python");and some
struct dirent *ent = readdir(dir);you might have
ent->d_name containing say
example.py .
The problem is when you do
stat(ent->d_name, &filestat)Because relative paths (including plain file names) given to
stat() refer to files and paths starting from the current working directory, you won't 'stat' the correct paths at all!
You are trying to obtain the information on files in the current working directory, that have the same name as files in the directory opened via
opendir().
The solution is to either construct the full path by combining the directory you used, a slash, and the entry
d_name field, or to use
fstatat(dirfd(DIR), ent->d_name, &filestat, 0);. However, if you do have
fstatat() available, you also have
scandir() available, in which case you're using the wrong tool for the job anyway.
Alternatively, you can just do a
chdir(target-directory) first, and
DIR *dir = opendir(".");.
And if you want to traverse entire directory trees, you'd better use
nftw(), or if you have a Microsoft-like deep dislike towards anything POSIX, the BSD-originating
fts interface.
Other than in very specific cases like kernel pseudofilesystems and having to be compatible with Windows, you should never use opendir()/readdir() directly, because you won't handle the cases where the directories are modified during scanning anyway. The proper interfaces are supposed to handle that sanely.