-1

I'm having a really weird issue that I can't seem to solve.

I am trying to stat the files in a directory in my C program but valid files are returning -1 (the file doesn't exist). The thing is, the files are valid and do have some data in them.

Another interesting thing is that the default directories . and .. are returning 0.

Below is my code:

#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <locale.h>
#include <langinfo.h>
#include <stdint.h>
#include <stdlib.h>

int main(int c, char *v[])
{
    int len;
    struct dirent *pDirent;
    DIR *pDir;
    char buffer[500] = {'\0'};
    char *files[10000];
    struct stat statbuf;
    int i = 0;
    int status;

    if (c < 2)
    {
        printf("Usage: testprog <dirname>\n");
        return 1;
    }
    pDir = opendir(v[1]);
    if (pDir == NULL)
    {
        printf("Cannot open directory '%s'\n", v[1]);
        return 1;
    }

    // http://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatat.html

    while ((pDirent = readdir(pDir)) != NULL)
    {

        strcpy(buffer, (const char *)pDirent->d_name);
        files[i] = malloc(strlen(buffer) + 1);
        strcpy(files[i], buffer);
        printf("buffer: %s \n", buffer);
        if (stat(pDirent->d_name, &statbuf) == -1)
        {
            perror("stat");
            exit(EXIT_FAILURE);
        }
        status = stat(pDirent->d_name, &statbuf);
        printf("status: %d \n", status);
        i++;
    }
    closedir(pDir);

    return 0;
}

The output when I run the stat command on the files within the directory is below:

buffer: test2
status: -1
buffer: .
status: 0
buffer: tset3
status: -1
buffer: ..
status: 0
buffer: test1
status: -1

Can someone please point me in the right direction? Pulling my hair out here.

Husk Rekoms
  • 483
  • 12
  • 22
  • 1
    `pDirent->d_name` is the file name, not the file full path – Jean-François Fabre Mar 10 '18 at 21:16
  • You need to print both `pDirent->d_name` and `strerror(errno)` after the call to `stat` that _fails_ - you're only doing that after the call that _succeeds_. I can't think of a good reason why two consecutive `stat` calls with the same arguments should have different results, but without knowing what `pDirent->d_name` and `strerror(errno)` are, we're guessing in the dark. – zwol Mar 10 '18 at 21:17
  • How can `status: -1` ever be printed when you exit if that's the case? – Siguza Mar 10 '18 at 21:17
  • Thanks, Jean-Francois. That's exactly what I was missing. – Husk Rekoms Mar 10 '18 at 21:24

1 Answers1

1

You need to concatenate the directory name with "/" and the dentry name and pass that to stat or you need to call fstatat with the directory's fd and the dentry name (or you need to be in the directory you're reading so that each dentry name is simultaneously a correct relative name).

Petr Skocik
  • 58,047
  • 6
  • 95
  • 142