Programming in standard c

E

Eric Sosman

CJ said:
Or, if you want both flexibility and
portability, you can do something like this (untested code):

if (... fopen failed ...) {
switch (errno) {

#ifdef EACCES
case EACCES:
/* handle permission error */
break;
#endif
[...]

But if you're not using POSIX, you could define EACCESS etc. as glocal
macros yourself, and then this code could break badly...

Such code is already broken, because Eanything is a
reserved identifier in any file that includes <errno.h>.
See section 7.26.3.

(Well, not "anything," exactly. Any identifier starting
with E and another upper-case letter or starting with E and
a digit is reserved. You can still use identifiers that
begin with E and a lower-case letter or with E and an underscore
or, I guess, with E and a suitable Unicode character, and the
identifier E itself is all right. But EACCESS etc. are reserved,
precisely to avoid the collisions that worry you.)
 
F

Flash Gordon

Malcolm McLean wrote, On 27/12/07 16:57:
The code is designed to be used in a production environment, and it is
adequate for that.

If you are prepared to limit yourself to environments where things work
as you expect, fine. However, that was NOT the challenge that Jacob posted.
It reads in a MiniBasic script file. If the file is
huge the function will fail, but the interpreter will choke on such an
input anyway.

The file being huge is not the main problem I was commenting on. The
main part I was commenting on was the use of things not guaranteed by
the standard when the challenge was to do it without going beyond the
guarantees of standard C.
 
K

Keith Thompson

CJ said:
Or, if you want both flexibility and
portability, you can do something like this (untested code):

if (... fopen failed ...) {
switch (errno) {

#ifdef EACCES
case EACCES:
/* handle permission error */
break;
#endif
[...]

But if you're not using POSIX, you could define EACCESS etc. as glocal
macros yourself, and then this code could break badly...

The implementation could do so, but a program could not; identifiers
starting with a letter E followed either an uppercase letter or a
digit are reserved.

You could test for whatever macro specifies POSIX conformance along
with the test for whether EACCES is defined; that would eliminate the
possibility of a non-POSIX implementation defining EACCES in some
incompatible way.
 
J

jacob navia

Erik said:
Your imagination is obviously not very good.

Take for example CP/M.

This system is a good example of a currently widely
used system isn't it?

The solution for that system is very simple.
filesize reports number of blocks times the size of each block.

Period. Of course this is not the size of the useful bytes but...
who cares? CP/M users know that!
Another example would be a file stored on a magnetic tape. There it might not be
possible to find out how large the file is without reading the file until
you reach an end-of-file marker. I am fairly certain that such devices
are still in use.

so what?

filesize searches till the end of the file is found or if the device is
not supported returns an error.

What is obvious is that there are two alternatives:

1) Take the worst possible file system. Then standardize only
what that file system supports.

2) Take the most common situation for current machines and file
systems and standardize what those systems support.

Obviously you support (1). Everybody has to take care of CP/M,
that disappeared more than 20 years ago, System 3090, that disappeared
more or less at the same date...

Yours is the easiest solution: keep C at the PDP-11 / CP/M System 3090
level.

I would propose that those obsolete systems aren't even considered.
If someone implements C in them, then, it is up to the implementation
to see how the standard can be implemented.

For instance, and to go on with CP/M you could store the number
of used bytes in each block at the last 2 bytes of each block
isn't it?

Not very difficult to do.
 
J

jacob navia

Eric said:
I repeat the question you snipped and have not yet even
begun to answer:

For file locked it could be a temporary problem. The program waits
for a certain period and retries.

For a privileges problem you change the file name so that it doesn't
use the name of a file already owned by someone else and retry.

For instance. There are thousands of variations.

Wait for a certain time is impossible in standard C. (As I said,
you can't do much in standard C). But that could be a portable
action if the interface level of C wouldn't be so low.
If you like, we can now rephrase it in terms of your list:
For each error code, please explain what "appropriate action"
(your phrase) should be taken, how its action differs from the
actions taken for other codes, and how to take action portably.

You do not understand. The appropriate action depends of the program
OF COURSE. A program may react to ENOENT with changing the mode
from read into write since it was testing if the file exists.
Another it would mean

DialogBox("Configuration file doesn't exist. Create it? (YN)");
Also, do you imagine that the list you exhibit here is an
exhaustive list of failure modes for fopen()?

There is no point in discussing if I address your complaint, and then
you bring it again. I answer it AGAIN and you bring it AGAIN.

I said that there is NO EXHAUSTIVE list. BUt a list with the most
common failures! I have told you this already THREE times.

PLEASE TAKE NOTICE ok?

What code should
an implementation use if fopen() fails for lack of memory?

ENOMEM or the defined portable error code for memory
exhaustion.
What
code reports an incompatibility between the file organization and
C's sequential "stream of bytes" model (c.f. OpenVMS)?

An error code specific to OpenVMS.

What code
is appropriate for a security violation (e.g., low-privilege
program attempting to read a high-privilege file -- note that your
description of EPERM does not cover this case)?

Another, system specific code. AS I TOLD YOU BEFORE
it is NOT exhaustive!

What code should
be used if the file name references an environment variable that
has no definition? What code should be used -- ah, the hell with
it. You have not even begun to think about these problems, much
less solve them.

I said in my message: <[email protected]>
<quote>
An implementation would be allowed to extend this errors but we could
portably test for a certain kind of error.
<end quote>

but you just ignore that and go on.
 
R

Richard Heathfield

jacob navia said:
This system is a good example of a currently widely
used system isn't it?

No, but *that's* a good example of moving the goalposts. You said you
couldn't imagine a file system that doesn't provide a way of knowing the
length of a file, so an example was provided for you. Now you seem to be
rejecting the example. Nevertheless, it is a valid example of a filesystem
that doesn't provide a way of knowing the length of a file. There's no
point in criticising answers that you yourself asked for, provided only
that they are correct. The above answer *is* correct, IIRC - CP/M does
indeed behave like that. Your criterion of "wide use" was not present in
your original question.
The solution for that system is very simple.
filesize reports number of blocks times the size of each block.

Period. Of course this is not the size of the useful bytes but...
who cares?

Not you, it seems. But there are people who have to write code that works
on arbitrary systems. You don't appear to be one of them. So? Just because
you are not such a person, that doesn't mean that such people don't exist.

I would propose that those obsolete systems aren't even considered.

Fortunately, those people who are responsible for the Standard are less
ready than you to dismiss systems that are in current use.

<snip>
 
B

Bart C

Richard Heathfield said:
jacob navia said: ....
Fortunately, those people who are responsible for the Standard are less
ready than you to dismiss systems that are in current use.

Someone creates a new OS with a file system having the innovative idea of
storing the byte-size of each file.

The question is, why would they do that? Because nobody would be allowed to
make use of it; not in Standard C anyway. Or other languages because they
are likely also implemented in C.

How then would a C programmer take advantage of this feature even though
it's only available on a billion or so computers?

Bart
 
A

army1987

jacob said:
you convert the __pos member into a long long.
That was not the point. fpos_t can be different things on different
systems, so, to portably convert it to a size, we would need another
function e.g. long fpos_t2bytecount(fpos_t), so why don't have the
function filesize directly return...
In any case I would say that a long long
result would be a better return type.

Indeed.
 
U

user923005

Yes, and furthermore you can still read from the file, or write to it,
*AFTER* someone else deletes it (until you fclose() it).


UNIX or POSIX.

My instance is not deleted until I exit the program. So the accuracy
of the fseek(), ftell() etc. functions is undamaged.
[Windows example of deleting failing on open file deleted.]
 
S

Stephen Montgomery-Smith

Bart said:
Someone creates a new OS with a file system having the innovative idea of
storing the byte-size of each file.

The question is, why would they do that? Because nobody would be allowed to
make use of it; not in Standard C anyway. Or other languages because they
are likely also implemented in C.

How then would a C programmer take advantage of this feature even though
it's only available on a billion or so computers?

Bart

Easy. The programmer would use one of the OS specific functions
supplied by the OS. For example, int stat(const char *path, struct stat
*sb). True, his code then becomes non-portable, but then again, he is
asking to do something inherently non-portable!

And most importantly, from a practical point of view, it really doesn't
seem to have stopped anyone from using C to do exactly this.

Stephen
 
C

CBFalconer

.... snip ... (Somebody fouled the attributions)
Yes, and furthermore you can still read from the file, or write
to it, *AFTER* someone else deletes it (until you fclose() it).


UNIX or POSIX.

I believe the quote should have been attributed to Jacob Navia, who
should now have his heels firmly mired in gooey astonishment.
Maybe he should also be shown sparse files?
 
B

Bart C

Eric Sosman said:
Bart C wrote:

Several things are wrong with it, even apart from the
possible 64KB limit.

I'll let that go.
Zeroth, you should have #include'd <stdio.h>. I'll let
you get away with this one, though, on the grounds that since

This is a code fragment. Assume headers are included for all C library
calls.
First, there's no error checking. None, nada, zero, zip.

I wasn't aware there was much to go wrong. But I will have a look. At worst
it will return the wrong file size; I'll make it return all 0's or or 1's or
something.
Second, ftell() returns a long. When you store the long

I'll change the types to long too, since it can't go past 2GB-1 anyway.
Third, what are the magic numbers 2 and 0 that you use
as the third arguments in the fseek() calls? My guess is
that they are the expansions of the macros SEEK_END and
SEEK_CUR on some system you once used, and that you've
decided for some bizarre reason to avoid using the macros.

Close. The code existed in a non-C language, but using the C runtime,
without access to the headers and it was easiest to plug in these constants.
Converted to C (and tested) for the post.
Fourth, for a text stream the value returned by ftell() is
not necessarily a byte count; it is a value with an unspecified
encoding. Calling it a "file size" makes unwarranted assumptions.

My assumption is the file is in binary mode; and my wrapper of the fopen()
function ensures that.
Fifth, there's 7.19.9.2p3: "A binary stream need not...
Sixth, for a binary stream there may be an unspecified...

I don't get these. There are known issues when used with files currently
open for writing. And I know the host OS in *my* case. But yes, anyone
attempting to use this code on their OS should be aware of limitations.
But other than that, it looks pretty good.

Thanks (?)

Bart
 
U

user923005

This system is a good example of a currently widely
used system isn't it?

The solution for that system is very simple.
filesize reports number of blocks times the size of each block.

Period. Of course this is not the size of the useful bytes but...
who cares?   CP/M users know that!

Here is a machine (HP RX/1600 Itanium running OpenVMS) that reports
its file sizes in blocks.

Next Cmd: dir/size

Directory DKA0:[000000.CONNX75.VMS-BINARIES]

LINK.COM;6 2
VAXCRTL.OPT;6 1
ZIP.AXP_OLB;6 730
ZIP.HLP;6 49
ZIP.I64_OLB;6 871
ZIP.VAX_DECC_OLB;6 218
ZIP.VAX_VAXC_OLB;6 201
ZIPCLI.AXP_OLB;6 292
ZIPCLI.I64_OLB;6 459
ZIPCLI.VAX_DECC_OLB;6
96
ZIPCLI.VAX_VAXC_OLB;6
84
ZIPCLOAK.AXP_OBJ;6 61
ZIPCLOAK.I64_OBJ;6 54
ZIPCLOAK.VAX_DECC_OBJ;6
22
ZIPCLOAK.VAX_VAXC_OBJ;6
22
ZIPNOTE.AXP_OBJ;6 70
ZIPNOTE.I64_OBJ;6 60
ZIPNOTE.VAX_DECC_OBJ;6
26
ZIPNOTE.VAX_VAXC_OBJ;6
26
ZIPSPLIT.AXP_OBJ;6 81
ZIPSPLIT.I64_OBJ;6 83
ZIPSPLIT.VAX_DECC_OBJ;6
31
ZIPSPLIT.VAX_VAXC_OBJ;6
29
ZIPUTILS.AXP_OLB;6 240
ZIPUTILS.I64_OLB;6 432
ZIPUTILS.VAX_DECC_OLB;6
62
ZIPUTILS.VAX_VAXC_OLB;6
59
ZIP_CLI.HLP;6 43

Total of 28 files, 4404 blocks.
Next Cmd:

each of those file sizes is 512 byte increments. You can buy a new
one today from HP, if you want.
http://h71000.www7.hp.com/openvms/hw_supportchart.html
so what?

filesize searches till the end of the file is found or if the device is
not supported returns an error.

What is obvious is that there are two alternatives:

1) Take the worst possible file system. Then standardize only
    what that file system supports.

2) Take the most common situation for current machines and file
    systems and standardize what those systems support.

Obviously you support (1). Everybody has to take care of CP/M,
that disappeared more than 20 years ago, System 3090, that disappeared
more or less at the same date...

Yours is the easiest solution: keep C at the PDP-11 / CP/M System 3090
level.

I would propose that those obsolete systems aren't even considered.
If someone implements C in them, then, it is up to the implementation
to see how the standard can be implemented.

For instance, and to go on with CP/M you could store the number
of used bytes in each block at the last 2 bytes of each block
isn't it?

Not very difficult to do.

The fact that sizes are not reported in bytes on some systems is not
nearly so large a hurdle as the fact that on live systems file sizes
are constantly changing. You are proposing a function that cannot
possibly work (reporting file size on a live file). It's not an
intelligent API.
 
U

user923005

Yes, but inflammatory exchanges is a major part of what makes this group
so fun to read.  So please don't discourage his participation!

Inflamatory exchanges do not lead to progress (IMO-YMMV).

If we are unable to act in a civil manner, it is an embarassment (or
should be).
 
C

CBFalconer

CJ said:
.... snip ...

But if you're not using POSIX, you could define EACCESS etc. as
glocal macros yourself, and then this code could break badly...

No you can't, because identifiers beginning with an uppercase E
have restrictions imposed on them. Read the C standard. Such a
definition imposes undefined behaviour.
 
S

Stephen Montgomery-Smith

user923005 said:
Inflamatory exchanges do not lead to progress (IMO-YMMV).

If we are unable to act in a civil manner, it is an embarassment (or
should be).

Well, yes, it should certainly be an embarrassment! But it is what it
is, so we may as well enjoy it for what it is.
 
J

jameskuyper

Bart said:
I wasn't aware there was much to go wrong. But I will have a look. At worst
it will return the wrong file size; I'll make it return all 0's or or 1's or
something.

Every single standard library function you called has a possibility of
failing. ftell() returns -1 when it fails; fseek() returns a non-zero
value when it fails. You check for neither possibility. Also, handle
might be an invalid pointer (which you unfortunately can't check in
any portable fashion), or it could be NULL (which you can).
 
J

jacob navia

user923005 said:
Here is a machine (HP RX/1600 Itanium running OpenVMS) that reports
its file sizes in blocks.

[big snip]
Total of 28 files, 4404 blocks.
Next Cmd:

each of those file sizes is 512 byte increments. You can buy a new
one today from HP, if you want.
http://h71000.www7.hp.com/openvms/hw_supportchart.html

If you have one of that systems and your trash is full so you can't get
rid of it, then you can do the following

http://h71000.www7.hp.com/wizard/wiz_5424.html
Obtaining RMS file size?
Hello Mr Wizard

I am looking for a method of obtaining the size of a file, NOT the
allocation
from within a Fortran routine. I thought this would be a simple
trivial task
but alas I am proved wrong.

Can you help.

Regards Jim
Answer
RMS does NOT keep track of the number of user data bytes in a file.
The only reliable way to obtain that, is to read the file and count!

So there you have the answer!

If you are using that system expect that filesize() will take some time.

So What?

Should we ALL suffer because some brain-dead system exists somewhere?
No.

Only the users of THAT system should be the ones of coping with their
choices not all others!
The fact that sizes are not reported in bytes on some systems is not
nearly so large a hurdle as the fact that on live systems file sizes
are constantly changing.

The function returns the size AT THE TIME OF THE CALL. I have repeated
this AGAIN AND AGAIN and I am repeating here AGAIN:

"AT THE TIME OF THE CALL"

If the file size changes later IT IS NOT THE PROBLEM OF THE API!

You are proposing a function that cannot
possibly work (reporting file size on a live file). It's not an
intelligent API.


If you say that because it takes a file pointer the file is "live"
that's another question. Maybe it would better be a file NAME and not a
handle to a file.

What is important is that we can use a portable function in MOST file
systems. I am tired of this levelling through the worst that is going on
here.

This insistence of getting the WORST system then FORCING all other
people to adapt themselves to that pile of sh...!

CP/M, it is DEAD.
OpenVMS? It is dying.

Anyway, I always avoided the VAX, and I am glad I did!
 
U

user923005

Well, yes, it should certainly be an embarrassment!  But it is what it
is, so we may as well enjoy it for what it is.

While I will admit that trollish posts are sometimes fun, the correct
model for posting is that of Tanmoy Bhattacharya and Chris Torek.
Which is to say:
Knowledgeable
Non-judgemental
Polite
Correct
Succinct
Informative
Interesting
etc.

Anything less is a defect on the part of the poster. My posts are
often defective. I also admit that when a troller is hanging like
some tempting Piñata, I am often prone to take a swing.
 
U

user923005

user923005 said:
Here is a machine (HP RX/1600 Itanium running OpenVMS) that reports
its file sizes in blocks.

[big snip]


Total of 28 files, 4404 blocks.
Next Cmd:
each of those file sizes is 512 byte increments.  You can buy a new
one today from HP, if you want.
http://h71000.www7.hp.com/openvms/hw_supportchart.html

If you have one of that systems and your trash is full so you can't get
rid of it, then you can do the following

http://h71000.www7.hp.com/wizard/wiz_5424.html
Obtaining RMS file size?
Hello Mr Wizard

I am looking for a method of obtaining the size of a file, NOT the
allocation
  from within a Fortran routine. I thought this would be a simple
trivial task
  but alas I am proved wrong.

Can you help.

Regards Jim
Answer
     RMS does NOT keep track of the number of user data bytes in a file.
     The only reliable way to obtain that, is to read the file and count!

So there you have the answer!

If you are using that system expect that filesize() will take some time.

So What?

Should we ALL suffer because some brain-dead system exists somewhere?
No.

Only the users of THAT system should be the ones of coping with their
choices not all others!

I have already said in previous posts that OpenVMS file size may be
obtained by table scan. This is a very unfriendly operation on a live
system and you had better have a darn good reason for doing it. You
have to lock each record as you read it to get a result that is
accurate even for what you saw at the instant of operations (and -- of
course -- each record may be changed or deleted the moment you move to
the next.
The function returns the size AT THE TIME OF THE CALL. I have repeated
this AGAIN AND AGAIN and I am repeating here AGAIN:

"AT THE TIME OF THE CALL"

But it can change the instant afterwards, so that information has
literally no value at all.
If the file size changes later IT IS NOT THE PROBLEM OF THE API!


If you say that because it takes a file pointer the file is "live"
that's another question. Maybe it would better be a file NAME and not a
handle to a file.

What is important is that we can use a portable function in MOST file
systems. I am tired of this levelling through the worst that is going on
  here.

The value of collecting a number that can change in an instant seems
rather strange. I assume you want to use it for something (such as
allocating memory so that you can read that file into memory). If the
number cannot be used for that (or any other) purpose, then what good
is the number?
This insistence of getting the WORST system then FORCING all other
people to adapt themselves to that pile of sh...!

CP/M, it is DEAD.
OpenVMS? It is dying.

We make millions of dollars off of OpenVMS. That includes plenty of
new development. The fact that such systems exist shows that your
arguments were simply wrong.
Anyway, I always avoided the VAX, and I am glad I did!

You are shown to be wrong. Did it make you feel foolish?
 

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

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,278
Latest member
BuzzDefenderpro

Latest Threads

Top