file bug

B

Bill Cunningham

I have written this file and decided to try error checking and eof
checking and there must be a bug somewhere. It compiled with djgpp fine. It
takes the win32/pe assembler as.exe and writes it to a.exe. I hope it's not
too hard to read. I'm stumped but that's expected and nothing new.

#include <stdio.h>
#include <stdlib.h>

main(){
char buf [2048];
FILE *fp;
fp=fopen("as.exe","rb");
if (fread(buf,sizeof(char),2048,fp)!=2048)
{if (ferror(fp))
{fprintf(stderr,"File error"); exit(1);}
if (feof(fp)) {fprintf(stderr,"EOF error"); exit (1);}}
fclose(fp);
fp=fopen("a.exe","wb");
fwrite(buf,sizeof(char),2048,fp);
fclose(fp);}

stdlib.h for exit()

Bill
 
B

Bill Cunningham

Oh yes I deliberately wrote it to fail. It only read 2048 bytes and the
file is about 202k.

Bill
 
M

Martin Ambuhl

Bill said:
I have written this file and decided to try error checking and eof
checking and there must be a bug somewhere. It compiled with djgpp fine. It
takes the win32/pe assembler as.exe and writes it to a.exe. I hope it's not
too hard to read. I'm stumped but that's expected and nothing new.

#include <stdio.h>
#include <stdlib.h>

main(){
char buf [2048];
FILE *fp;
fp=fopen("as.exe","rb");
if (fread(buf,sizeof(char),2048,fp)!=2048)
{if (ferror(fp))
{fprintf(stderr,"File error"); exit(1);}
if (feof(fp)) {fprintf(stderr,"EOF error"); exit (1);}}

This is certainly not what you intend to do, unless you are
somehow magically guaranteed that the file when read magically fills a
2048 byte buffer without remainder.
On reaching end-of-file you want to write out the buffer and close the
output file. You do _not_ want to call it an error and abort.

And your use of exit(1) is not portable. The only portably defined
values for exit are 0, EXIT_SUCCESS, and EXIT_FAILURE. None of them
need be equal to 1.
 
B

Bill Cunningham

This is certainly not what you intend to do, unless you are
somehow magically guaranteed that the file when read magically fills a
2048 byte buffer without remainder.

What can I do about this? If I wanted to read a file that is 200k or one
that is 300mB? Do you always have to look at the file to see how big it is?
On reaching end-of-file you want to write out the buffer and close the
output file. You do _not_ want to call it an error and abort.

And your use of exit(1) is not portable. The only portably defined values
for exit are 0, EXIT_SUCCESS, and EXIT_FAILURE. None of them need be
equal to 1.

I wanted to overflow this program and test the eof or error checking.

Bill
 
B

Bill Cunningham

Would the answer to reading a file of unknown size involve fseek() and
or fpos() ?

I also wanted this file to crash and it certainly didn't. So I'm asking two
questions here.

1) How can I get a file like the one I wrote to fail so I would see
fprintf(stderr,"EOF error");

2) How would you read into buffer the size of a file when the size is
unknown? fseek() or fpos() involved ?

Bill
 
G

Gordon Burditt

Would the answer to reading a file of unknown size involve fseek() and
or fpos() ?

Often, you keep reading bytes until you hit the end of file. No
seeking involved. Hitting end of file is *not* usually considered
an error; it is expected you'll hit it eventualy. You might hit
end of file at an unexpected place, e.g. in the middle of a C
comment and consider that an error.
I also wanted this file to crash and it certainly didn't. So I'm asking two
questions here.

Files don't crash, programs crash. And hitting end of file isn't
normally considered a "crash", and a program hitting that shouldn't
react with a crash.
1) How can I get a file like the one I wrote to fail so I would see
fprintf(stderr,"EOF error");

Keep reading in a loop, stopping only when you get EOF or an error.
2) How would you read into buffer the size of a file when the size is
unknown? fseek() or fpos() involved ?

Keep enlarging the buffer (with realloc()). When you get end-of-file,
reduce the size of the buffer to the size of all the data actually
read. Or read the file in pieces and never try to have the whole
file in memory at one time.
 
B

Bill Cunningham

Keep enlarging the buffer (with realloc()). When you get end-of-file,
reduce the size of the buffer to the size of all the data actually
read. Or read the file in pieces and never try to have the whole
file in memory at one time.

So this is the step for reading a file til EOF and saving it to another
name? Basically cp or copy a 'to' b ?

Bill
 
M

MisterE

Bill Cunningham said:
What can I do about this? If I wanted to read a file that is 200k or
one that is 300mB? Do you always have to look at the file to see how big
it is?

You can easily get the size of a file:
FILE *in;
char *filedata;
long size_in_bytes;
in=fopen("file.txt","rb");
fseek(in,0,SEEK_END);
size_in_bytes = ftell(in);
fseek(in,0,SEEK_SET);
filedata = malloc(size_in_bytes);
fread(in,sizeof(char),size_in_bytes);
 
M

MisterE

Bill Cunningham said:
Oh yes I deliberately wrote it to fail. It only read 2048 bytes and the
file is about 202k.

What do you mean it doesn't fail? Why should it it says to read 2k and write
2k. It will do that and end.
 
B

Bill Cunningham

Keep enlarging the buffer (with realloc()). When you get end-of-file,
reduce the size of the buffer to the size of all the data actually
read. Or read the file in pieces and never try to have the whole
file in memory at one time.

So I'll need a buffer for fread and write.
char buff(10);
And a pointer for realloc
char *b=&buff;
Something like that right?

Bill
 
V

vippstar

So I'll need a buffer for fread and write.
char buff(10);
And a pointer for realloc
char *b=&buff;
Something like that right?
No, not something like that, and you know it.
It is not a learning issue when you have 'char buf(10);' or 'char
*b=&buff' in your code.
It's a matter of lazyness or you are trying to troll. It wouldn't
compile.
You want to raise discussions over why would one put a whole file in
memory or why ftell() is not reliable et cetera.

As it's been told to you before: either put the whole file in memory
OR read it in chunks/blocks.
Do not further ask here how to do that, go read about
malloc(),realloc(),fread(),fseek(),ftell() (the latter two, you don't
even need)
If you don't understand what these functions do or return, don't ask
here, read about them again.

And in your future posts, please avoid mentioning assemblers, file
formats and operating systems.
That is, if you are not troll.
 
R

Richard Heathfield

MisterE said:
You can easily get the size of a file:
FILE *in;
char *filedata;
long size_in_bytes;
in=fopen("file.txt","rb");

What if fopen returns NULL?
fseek(in,0,SEEK_END);

SEEK_END is not guaranteed to be meaningful for binary files.
size_in_bytes = ftell(in);
fseek(in,0,SEEK_SET);
filedata = malloc(size_in_bytes);

What if malloc returns NULL?
fread(in,sizeof(char),size_in_bytes);

fread takes more than three parameters.
 
G

Gordon Burditt

Keep enlarging the buffer (with realloc()). When you get end-of-file,
So this is the step for reading a file til EOF and saving it to another
name? Basically cp or copy a 'to' b ?

A more usual way to copy a file is to read a chunk of it into a
buffer, then write the number of bytes you read to the copy. Repeat
(re-using the same buffer) until you get end-of-file trying to read
more data. What's a "chunk"? Any size you want, from one byte to
billions of terabytes, provided your system can handle it.

For efficient copies, a buffer size of one or a few disk blocks
(e.g. 512 bytes to 16Kbytes on common systems available today) might
work better than waiting to read the whole (terabyte) file before
writing any of it.
 
M

MisterE

SEEK_END is not guaranteed to be meaningful for binary files.

Why exactally doesn't it work?
I know C99 7.19.9.2 says:

A binary stream need not meaningfully support fseek calls
with a whence value of SEEK_END.

I know the standard says it need not, but so what? 99.9999% of compilers do,
and those that don't probably don't support fseek at all.
 
R

Richard Heathfield

MisterE said:
Why exactally doesn't it work?

On platforms where it works, of course it /does/ work. But the Standard
mentions the possibility that it may fail because there really are
implementations where it /does/ fail because of the way the filesystem
works (basically, some filesystems put an arbitrary amount of padding at
the end of a file).
I know C99 7.19.9.2 says:

A binary stream need not meaningfully support fseek calls
with a whence value of SEEK_END.

I know the standard says it need not, but so what? 99.9999% of compilers
do, and those that don't probably don't support fseek at all.

Well, I question your 99.9999%, since there are probably something like a
hundred or so mainstreamish C compilers out there, of which a small
handful (one? two? four? nine? who knows?) don't provide meaningful
support for SEEK_END on binary files. If your code never has to run on any
of these implementations, then yes, sure, so what? But if it ever does
have to, then of course it matters. Obviously you know your user base
better than I do, so you're in a better position than I am to judge
whether you need to be this cautious.
 
N

Nick Keighley

    I have written this file and decided to try error checking

but you failed to check if the fopen() calls succeeded
and eof
checking and there must be a bug somewhere.

you suffer from the illusion that EOF is an error.
It compiled with djgpp fine. It
takes the win32/pe assembler as.exe and writes it to a.exe. I hope it's not
too hard to read.

your layout is horrid

I'm stumped but that's expected and nothing new.

<snip code>

in later posts you ask how to copy a file and don't
seem to understand the answer.

in pcode:

LOOP UNTIL NO MORE DATA
read;
write;
END


in C

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char buf [2048];
FILE *fp_in;
FILE *fp_out;
size_t ch_read;

if ((fp_in = fopen ("as.exe", "rb")) == NULL)
{
fprintf (stderr, "failed to open input file\n");
exit (EXIT_FAILURE);
}

if ((fp_out = fopen ("a.exe", "wb")) == NULL)
{
fprintf (stderr, "failed to open output file\n");
fclose (fp_in);
exit (EXIT_FAILURE);
}

do
{
if ((ch_read = fread (buf, 1, sizeof(buf), fp_in)) !=
sizeof(buf)
&& ferror(fp_in))
{
fprintf (stderr, "read error\n");
fclose (fp_in);
fclose (fp_out);
exit (EXIT_FAILURE);
}

if (fwrite (buf, 1, ch_read, fp_out) != ch_read)
{
fprintf (stderr, "write error\n");
fclose (fp_in);
fclose (fp_out);
exit (EXIT_FAILURE);
}
}
while (ch_read == sizeof(buf));

fclose (fp_in);
fclose (fp_out);

return 0;
}


this compiles and runs without error but is otherwise untested.
Oh, the output file is the same size as the input file.


--
Nick Keighley

A ruby trembled. Two tourmaline nets failed to rectify the laser beam.
A diamond noted the error. Both the error and the correction went into
the general computer.
Corwainer Smith "The Dead Lady of Clown Town"
 
D

Default User

Nick said:
but you failed to check if the fopen() calls succeeded

This is an example of why I stopped dealing with Bill. He had a
previous problem using file-handling, and I wanted him to work on that
exercise until it was complete and he understood all the aspects of the
functions he was trying to use. He refused, and skipped off to a series
of other problems, NONE of which he's come anywhere close to working
satisfactorily.

He's wasting eveyone's time. Whether he's a long-con troll or truly
learning-disabled doesn't matter. If it's the latter, then everyone
just has to accept that programming is not for him. He doesn't show any
capability to concentrate on a problem long enough to complete it.

He could study C for a hundred years and not be a capable practicioner.
Not every endeavor is for every person. He either needs to follow the
instructions of the people here or give up.




Brian
 
B

Bill Cunningham

in pcode:

LOOP UNTIL NO MORE DATA
read;
write;
END


in C

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char buf [2048];
FILE *fp_in;
FILE *fp_out;
size_t ch_read;

if ((fp_in = fopen ("as.exe", "rb")) == NULL)
{
fprintf (stderr, "failed to open input file\n");
exit (EXIT_FAILURE);
}

if ((fp_out = fopen ("a.exe", "wb")) == NULL)
{
fprintf (stderr, "failed to open output file\n");
fclose (fp_in);
exit (EXIT_FAILURE);
}

do
{
if ((ch_read = fread (buf, 1, sizeof(buf), fp_in)) !=
sizeof(buf)
&& ferror(fp_in))
{
fprintf (stderr, "read error\n");
fclose (fp_in);
fclose (fp_out);
exit (EXIT_FAILURE);
}

if (fwrite (buf, 1, ch_read, fp_out) != ch_read)
{
fprintf (stderr, "write error\n");
fclose (fp_in);
fclose (fp_out);
exit (EXIT_FAILURE);
}
}
while (ch_read == sizeof(buf));

fclose (fp_in);
fclose (fp_out);

return 0;
}


this compiles and runs without error but is otherwise untested.
Oh, the output file is the same size as the input file.


Whoa. Wow that's a lot of code I'll copy and try to digest it. I don't
see enough simple code to get readily. I've never seen do used for this and
never used it myself. I'll compile and study it thanks.

Bill
 
B

Bill Cunningham

You can easily get the size of a file:
FILE *in;
char *filedata;
long size_in_bytes;
in=fopen("file.txt","rb");
fseek(in,0,SEEK_END);
size_in_bytes = ftell(in);
fseek(in,0,SEEK_SET);
filedata = malloc(size_in_bytes);
fread(in,sizeof(char),size_in_bytes);

Ok thanks I need to see as much simple code as I can. All that I seem to
get hold of is written in shorthand and such.

Bill
 
B

Bill Cunningham

[snip]

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
char buf [2048];
FILE *fp_in;
FILE *fp_out;
size_t ch_read; /*cool. */

if ((fp_in = fopen ("as.exe", "rb")) == NULL)
{
fprintf (stderr, "failed to open input file\n");
exit (EXIT_FAILURE);
}

if ((fp_out = fopen ("a.exe", "wb")) == NULL)
{
fprintf (stderr, "failed to open output file\n");
fclose (fp_in);
exit (EXIT_FAILURE);
}

do
{
if ((ch_read = fread (buf, 1, sizeof(buf), fp_in)) !=
sizeof(buf)

absolutlely brillant. I always wondered how to deal with these return
values. Since fread returns a size_t declare a size_t to hold the return
value and use = to assign. Other than the fp=fopen example I haven't seen
this much. Not in code that I can read.

&& ferror(fp_in))
{
fprintf (stderr, "read error\n");
fclose (fp_in);
fclose (fp_out);
exit (EXIT_FAILURE);
}

if (fwrite (buf, 1, ch_read, fp_out) != ch_read)
{
fprintf (stderr, "write error\n");
fclose (fp_in);
fclose (fp_out);
exit (EXIT_FAILURE);
}
}
while (ch_read == sizeof(buf));

fclose (fp_in);
fclose (fp_out);

return 0;
}


this compiles and runs without error but is otherwise untested.
Oh, the output file is the same size as the input file.


I'll tell you I can read very little of any C code I come across because
it's written by people who know what they're doing and they take shortcuts
in writing and it just leaves me in the dust. This I can make out enough to
not be just confused and actually learn a little.

Bill
 

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

Can not read VCD file in Linux 8
URGENT 1
error 28
fread/fwrite 2 18
Working with files 1
malloc 40
no error by fscanf on reading from output file 18
Cgi and file access 8

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top