Mr John FO Evans said:
After reading all the comments on this thread I am astounded that the 'C'
standard does not require that fopen returns a meaningful error when it
fails. Surly this is an ommision - or perhaps it is a acceptance that
computer systems suppliers do not like standards and hence do not provide
meaningful error returns from their lower level routines?
Not at all. The C standard merely doesn't require *all*
implementations to report why fopen() failed. This allows C to be
implemented on a wide variety of systems, some of which may not always
provide meaningful information about errors.
The only errno values required by the C standard are EDOM, EILSEQ, and
ERANGE. (The corresponding error messages on one system are "Argument
out of domain", "Illegal byte sequence", and "Result too large",
respectively.)
But implementations are free to set errno on a failed fopen(), and to
provide more error codes than the minimal set required by the standard
-- and in fact most implementations do so.
Something like this:
errno = 0;
if ((f = fopen(filename, "r")) == NULL) {
perror(filename);
}
is very likely to give a meaningful error message on most systems --
and in fact is guaranteed to do so on many systems. If your
implementation doesn't give you a meaningful error message, you can
still complain to your vendor; you just can't argue that the
implementation doesn't conform to the C sftandard.
Having said that, I will acknowledge one weakness. There's no way for
a program to tell whether the implementation sets errno to a
meaningful value. You can generally tell by reading the
implementation's documentation, but that's not very helpful if you're
trying to write portable code.
If fopen() fails and errno is non-zero, it's possible that it was set
by some function called by fopen() for reasons having nothing to do
with fopen's failure. For example, fopen() might call malloc(),
malloc() could fail and set errno, then fopen() could fall back to
some alternative mechanism that doesn't use dynamically-allocated
memory, and then fail because the file doesn't exist. (That
particular scenario isn't very plausible, but something along those
lines could happen.)
It might have been more convenient if each library function defined in
the standard were required on failure to either (a) set errno to a
meaningful value, or (b) reset it to the value it had before the call.
If that were the case, then this:
errno = 0;
if ((f = fopen(filename, "r")) == NULL) {
if (errno == 0) {
fprintf(stderr, "fopen failed for %s\n", filename);
}
else {
perror(filename);
}
}
could always be depended on to produce a meaningful error message.