tags:

views:

184

answers:

3

I'd like to perform a quick check whether or not a file can be opened. It should be written in portable C, or at least to work on Win32 and POSIX systems. #ifdefs are acceptable.

I'm trying to avoid this:

int openable(const char*filename) {
    FILE *f = fopen(filename,"r");
    if (!f)
        return 0; /* openable */
    fclose(f);
    return 1; /* not openable */
}

From what I can tell stat(), in its simplest form, can be used to check if file exists, but not to check if it's actually openable.

+2  A: 

There are many factors you would need to check before you can know a file is "openable", and trying to check them all in a cross-platform way would be silly.

I think what you are doing now is simple and safer. However remember that just because a file is "openable" now doesn't mean that it still will be when you actually come to open it. Nothing prevents it changing in the meantime.

MattJ
My comment is at Michael's response :)
Ivan Vučica
+1  A: 

I think what you have is probably about as good as you'll get (though your comments are reversed from what they should be). There are many things that can prevent a file from opening: permissions, something else holding it open, lack of resources, etc.

To go through all of these checks accurately, you might as well just open the thing.

However, note also that on most systems, what you return could be a lie to the caller - by the time you've returned an indication to the caller about whether the file can be opened or not, the state of the systems could change (something that held the file open exclusively could close it for example). So the only truly effective way for an application to know whether they can open and use a file is to just open and use the file (and handle any failures).

In other words, if you return 'true' to your caller, they could try to open the file and it might still fail.

Michael Burr
Thanks, however this is mostly to decide which config file will be loaded without major restructuring of the code. Luckily this is a one time operation during launch of the server, so it's not likely to fail.
Ivan Vučica
Note that even if you get good at checking permissions on files via 'stat()', for example, if there are ACLs in use, you won't find out whether the file can be opened unless you look for those too.
Jonathan Leffler
+2  A: 

The POSIX standard solution is access(), which is also in the Windows runtime as _access().

I guess it is slighly better than fopen()+fclose() because:

  • It is a well-known, standard solution to the problem of testing a file for access rights
  • It is very probably faster, with less memory overhead

Of course, it is just as susceptible to race conditions as any other way of doing such a test. In a way, the only safe way to know if a file is availble for reading is to open it and try to read, without closing it in between. Even then, you still need to watch for "unexpected" EOF, of course. I/O is hard.

unwind
beware that access() may tell you that you can't access files in setuid programs, even those files that fopen() will open just fine: http://www.gnu.org/software/libtool/manual/libc/Testing-File-Access.html
dmityugov
Thanks, unwind, did't know about access(), this is what I was looking for. Race conditions are not really a problem in what I'm doing :)dmityugov, thanks a lot for the comment, I'll be careful about this!
Ivan Vučica
I think the original solution is probably preferable to access(), actually. It's possible that access() will be slightly faster than fopen()/fclose(), but there are all sorts of edge cases (setuid, or ACLs, or race conditions) where access() won't actually tell you whether you can read a file.
Mark Bessey