3

Using PellesC on Windows 8.1.

I know this topic has been addressed many times with many solutions. I have read solutions stating the usage of CreateFile, PathFileExists, GetFileAttributes, _access which I somewhat understand.

I have also read an important point about race conditions in the answer to the questions Quickest way to check whether or not file exists and What's the best way to check if a file exists in C? (cross platform).

So if I open a file using fopen() in C and when it fails (for any reason) and passes NULL back; then can I further check for errno == ENOENT and be content with it and report correctly that the file does not exists.

#include <stdio.h>
#include <string.h>
#include <errno.h>

int file_exists(char filename[]) {
    int err = 0; //copy of errno at specific instance
    int r = 0;   //1 for exists and 0 for not exists
    FILE *f = NULL;

    //validate
    if (filename == NULL) {
        puts("Error: bad filename.");
        return 0;
    }

    printf("Checking if file %s exists...\n", filename);

    //check
    errno = 0;
    f = fopen(filename, "r");
    err = errno;
    if (f == NULL) {
        switch (errno) {
          case ENOENT:
            r = 0;
            break;
          default:
            r = 1;
        }
        printf("errno = %d\n%s\n", err, strerror(err));
    } else {
        fclose(f);
        r = 1;
    }

    if (r == 0) {
        puts("It does not.");
    } else {
        puts("It does.");
    }

    return r;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Jazz
  • 639
  • 1
  • 11
  • 28
  • 1
    If you want to report back the cause of the error to the user, then using `errno` is indeed what you want. If you want to know if a file *exists*, then the absence of an `ENOENT` does not guarantee that (you could have gotten another error like `EPERM` eg., or the file could have been created as part of the `fopen` call, or ...). Can you describe in a bit more detail what you're trying to achieve ? – Sander De Dycker Sep 05 '18 at 06:33
  • I shall post code. wait a minute. – Jazz Sep 05 '18 at 06:35

1 Answers1

6

fopen needs to do lots of stuff and checking before the file is opened. ENOENT implies that the file does not exist, but file not existing does not imply ENOENT.

It is possible for a file to not exist and you to get another error, such as EACCES for not being able to read the parent directory for example.


On the other hand, ENOENT from fopen does not mean that some other process couldn't have created the file even before fopen returns or before you're inspecting the errno and so on; this is the reason why C11 added the x flag for opening a file for writing in exclusive mode - failing if the file already exists.


To sum it up: if you get ENOENT, the file did not exist when you tried opening it. If you get some other error, then each other error code would belong to one of 3 these classes - that it is certain that either

  • the file existed, or
  • it cannot have existed
  • or it might have existed at the time

at the time of opening. It is up to you and your required logic how you'd handle these other errors. A simple way would be to refuse to continue processing, reporting the error to the user.