0

I'm trying to list file infos(including directories etc) using stat()

It works fine when I give "."(current directory) as argv[1] (ex. $./a.out .)

but has an error when I give other directory such as "..", "/" etc.

stat function returns -1(fail) when after direntp points ".."(parent directory).

here's an example.

$ ls -a ..
. .. sample temple

$ ./a.out ..
Success: .
Success: ..
Fail: sample
Stat Call Error.
Terminate.

$

So why does it fail when I give other path to argument of stat()?

here's my code below

#include "stdio.h"
#include "dirent.h"
#include "sys/stat.h"
#include "unistd.h"
#include "stdlib.h"

int main(int argc, char const *argv[])
{
    DIR *dirp;
    struct dirent *direntp;
    struct stat statbuf;

    dirp = opendir(argv[1]);
    while((direntp = readdir(dirp)) != NULL)
    {
        if(direntp->d_ino == 0)
            continue;
        if(direntp->d_name[0] != '.'); /* doesn't matter, This isn't a mistake */
        {
            if(stat(direntp->d_name, &statbuf) == -1)
            {
                printf("Fail: %s\n", direntp->d_name);
                printf("Stat Call Error\n");
                exit(-1);
            }
            printf("Success: %s\n", direntp->d_name);
        }
    }
    closedir(dirp);
    return 0;
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
Jinmae Jin
  • 19
  • 1
  • 4
  • 2
    `if(stat(direntp->d_name, &statbuf) d_name);` : does that compile? – Jean-François Fabre Nov 30 '16 at 21:40
  • I fixed code. left bracket was omitted cuz it is regarded as a tag in html, so I changed to == -1 – Jinmae Jin Nov 30 '16 at 21:50
  • 2
    `if(direntp->d_name[0] != '.');` means that everything after that line runs without regard to the value of `direntp->d_name[0]` – KevinDTimm Nov 30 '16 at 21:52
  • `doesn't matter, This isn't a mistake` No it isn't a syntax error, but it is effectively a no-op and complete nonsense. (and you should not exit on stat() faulre but just continue (Because of race conditions, for instance)) – wildplasser Nov 30 '16 at 22:05

1 Answers1

3

The opendir function returns directory contents using relative path, not absolute.

When you're not scanning the current directory, you only have the name of the entry, but not its full path, so stat fails on all entries because it looks them up in the current directory (but . and .. which also exist in the current directory).

Of course it works in the current directory, where you don't have this problem.

Fix: compose the full pathname, ex like this:

char fp[PATH_MAX];
snprintf(fp, sizeof(fp), "%s/%s", argv[1], direntp->d_name);
if(stat(fp, &statbuf)) {
...
penguin359
  • 1,289
  • 13
  • 26
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219