questions on ftell and fopen

  • Thread starter subramanian100in
  • Start date
C

Chris Torek

[regarding using strerror(errno) or equivalent to expand on
something like "fopen failed", despite the C Standard not
promising that fopen failure must set errno appropriately]

We're not talking about a failure here, we're talking about
the quality of an error message. On a good implementation,
perror() will generate a reasonable error message. On
a poor implementation, the error messsage will be less
helpful.

Indeed.

In the past, I have suggested -- and will continue to suggest --
that if you cannot depend on the implementation to go "above
and beyond" the Standard C requirements, you can do something
like this:

/* optional: errno = 0; */
fp = fopen(path, mode);
if (fp == NULL) {
fprintf(stderr, "unable to open %s; most recent system error was %s\n",
path, strerror(errno));
... do whatever else is appropriate here ...
}
Is it any more helpful to output:
"operation failed, and this implementation is so broken
that I can't tell you why." than it is to output a message
based on an incorrect value of errno? (well, yeah, I
guess it is...but not by much.)

In this case, you might get (using a slightly different format):

prog: can't open foo.txt for reading;
most recent system error was "no such process"

on a "bad" system, and:

prog: can't open foo.txt for reading;
most recent system error was "too many open files"

on a "good" system. (And in fact, some pre-POSIX Unix-based systems
*would* fail to set errno if you had the maximum number of files
-- 20 -- open, so that the stdio routines in the C library ran out
of "FILE" objects and never made any system calls. If you were to
set errno to 0 before calling fopen(), strerror(errno) would be
"no error" or "success" or similar.)
I suppose I'll raise my standards and make a point
to only claim POSIX conformance for my code. Time
to remove -ansi from CFLAGS, I guess...

In this particular case, I would have been happy to see the C
standards require fopen(), malloc(), and other such functions to
set errno on failure (ideally, C89 and C99 both, but any upgrade
along the way would have been welcome). But we must make do with
what we have. :)
 
C

CBFalconer

Bill said:
.... snip ...

I suppose I'll raise my standards and make a point
to only claim POSIX conformance for my code. Time
to remove -ansi from CFLAGS, I guess...

That's lowering your standards. The appropriate thing is to
isolate code that requires something that ISO does not guarantee,
and compile those modules alone with relaxed standards.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>

"A man who is right every time is not likely to do very much."
-- Francis Crick, co-discover of DNA
"There is nothing more amazing than stupidity in action."
-- Thomas Matthews
 
K

Keith Thompson

I wrote the above. Gordon, I do not give you permission to quote
anything I write here, either directly or indirectly, without
attributing it to me.
Since the standard doesn't guarantee that a failing fopen() does *NOT*
set errno, you should output it as part of an error message.

That's highly questionable.

[...]
If it is known that fopen() will set errno to ENOMEM if it runs out
of memory, and ENOTTY (misleading at best) if opening the file
fails, then printing "operation failed: Not a typewriter" is an
improvement over a generic "operation failed and I don't have a
clue why", because in at least one circumstance (running out of
memory) it provides a better answer.

And how is this known? If you happen to know what fopen() will set
errno to for certain failures, and that those errno values happen to
be meaningless in some cases, you can write system-specific code to
translate the error codes to something meaningful.

Whether a generic "open failed" is better or worse than a misleading
"open failed: Not a typewriter" depends on the audience, i.e., who's
going to be seeing the error message and acting on it.
 
F

Flash Gordon

Bill Pursell wrote, On 04/03/07 19:45:
So how do you deal with it? Do you write a wrapper like the
following around every libc function that the standard doesn't
require to set errno? It seems rather kludgy.

<snip>

Actually we have one general purpose error handling function that checks
errno (and other error flags that either our code or other libraries
might have set) and reports errors appropriately. If we have got the
rest of the code write in terms of when errno and the other flags are
cleared (we are not perfect, but not doing too badly) then if greatly
increases the chance of a sensible error message.

Customers in my experience strongly dislike error messages that are
obviously garbage.
 
F

Flash Gordon

Bill Pursell wrote, On 04/03/07 21:03:
Bill Pursell said:
On Mar 4, 11:13 am, Flash Gordon wrote:
Bill Pursell wrote, On 04/03/07 06:57:
On Mar 3, 8:06 pm, Keith Thompson wrote:
It's likely to do so on most systems, but the standard doesn't
actually guarantee that a failing fopen() sets errno.
True. However, it strikes me that it is NOT the
programmer's responsibility to account for inadequacies
of the implementation.
Wrong IMHO. It is the programmer's responsibility to produce software
that works correctly on whatever system the customer wants even if the C
implementation on that system is completely useless.
So how do you deal with it? [...]
You can save a copy of errno and set errno to 0 before calling
fopen, then on fopen failure only print a message based on errno
if errno is nonzero.

I don't see that the standard guarantees that fopen will
not modify errno if it is succesful. Is there such a
guarantee? Or that fopen() won't fail and set errno
to a totally unrelated non-zero value, and give me:
foo: Invalid cross-device link

Quite correct.
It seems to me that you have to rely on the implementation
for something, or you'll just go insane. I'll stick
with simply calling perror() (or err() or error()) but
I'm not going to reimburse Flash if his customer leaves. :)

I never said it has to be perfect (nothing ever is) or work on *every*
system, just that it is the programmers responsibility to get it working
on whatever systems the customer wants to use even if those systems are bad.

If all the systems you are interested in will do something sensible if
you just call perror (you won't get "File open failed because of
askdjnfaskjdbnfsdb") then you have done what is required. So if you will
accept I have to deal with systems that don't behave in what I consider
a sensible manner you don't have to reimburse me :)
 
R

Randy Howard

That's lowering your standards.

Only if you have some made-up belief that one standard is better than
another. Otherwise you are just picking a different standard.
The appropriate thing is to
isolate code that requires something that ISO does not guarantee,
and compile those modules alone with relaxed standards.

That is an approach, but not the only one that is "appropriate", that
is dependent upon too many variables to claim generically.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

URGENT 1
Linux: using "clone3" and "waitid" 0
Question about change of "fp" in function "fseek"and "ftell" 3
seg fault 76
fseek 17
Command Line Arguments 0
Help with EXT3 Filesystem work 1
error 28

Members online

Forum statistics

Threads
473,780
Messages
2,569,608
Members
45,241
Latest member
Lisa1997

Latest Threads

Top