fseek on a position beyond EOF does not trigger EOF using feof, how come?
Asked Answered
H

4

17

I'm reading data from a file to memory that is opened with:

FILE *f = fopen(path, "rb");

Before I start copying bytes from the file I seek to a start position using:

/**                                                                                                                                                    
 * Goes to the given position of the given file.                                                                                                       
 *                                                                                                                                                     
 * - Returns 0 on success                                                                                                                              
 * - Returns -1 on EOF                                                                                                                                 
 * - Returns -2 if an error occured, see errno for error code                                                                                          
 * - Returns -3 if none of the above applies. This should never happen!                                                                                
 */                                                                                                                                                    

static int8_t goto_pos(FILE *f, uint64_t pos)                                                                                                          
{                                                                                                                                                      
        int err = fseek(f, pos, SEEK_SET);                                                                                                             

        if (err != 0) {                                                                                                                                
                if (feof(f) != 0) return -1;                                                                                                           
                if (ferror(f) != 0) return -2;                                                                                                         
                return -3;                                                                                                                             
        }                                                                                                                                              

        return 0;                                                                                                                                      
}

The problem is that even though I seek to a position way beyond EOF, this function never returns -1.

According to the reference feof should return a non zero value when EOF is encountered.

Why is this? Is the feof function useless?


Note that I'm currently using the return value of fgetc to check for EOF.

Hobard answered 23/6, 2013 at 18:18 Comment(10)
Where in fseek's docs did you see that it would set the EOF flag?Adkison
@Mat: The OP's does not explicitly sais this ...Louielouis
(@alk: that was a hint to the OP to go check the man page/POSIX reference/whatever applicable)Adkison
@Mat: Ah, yes sure! Forgot that reading is out of fashion. Btw: Are the already video-version of the man-pages around in one or the other distro? ;->Louielouis
@alk: Why do you feel the need to be condescending? It doesn't help me or anyone else.Hobard
@Adkison I used this reference. I didn't see that fseek set the flag, I just assumed that seeking past EOF would set the flag. It seemed logical to me.Hobard
I did not meant this be taken personaly. Please excuse the somewhat cynical try to push peoble to read documentation. Btw: In the general case it is a good idea to turn the documentation delivered with the tool isself, the man pages that come with the development tool chain on Linux in this case.Louielouis
@alk: Thank you, no harm done. Like I said to Mat, I have read the documentation. It's just that sometimes you miss stuff, especially when you are new to an API or programming language. Maybe the man pages are the best reference?Hobard
If uncertainties arise it is always advisable to consult more than one source of information. A good reference on "how it shall be" is the standard: pubs.opengroup.org/onlinepubs/9699919799/idx/functions.html (POSIX), an overview what's in the GNU libc: gnu.org/software/libc/manual/html_node/… and finally the man pages could be read from the source here: manpages.debian.net/cgi-bin/man.cgi (without any annoying ads!)Louielouis
Alright, thanks for the tip!Hobard
L
21

Seeking simply does not test for the file's end.

The reason for this is that you perhaps might want to do an fwrite() where you sought to. fseek() can not know what your plans are for after it was called.

Do an fread() after seeking behind the file's end and you will have feof() returning a non-zero value.

Louielouis answered 23/6, 2013 at 18:21 Comment(3)
Not only does seeking not test for eof; it clears the eof flag.Kiely
Thanks for explaining! Then feof will be no use for me since I'm using fgetc and checking for the EOF return value anyway.Hobard
OP did open the stream in "rb" mode, this fseek behavior does not make anysense for read-only file.Ehlke
O
6

feof() is set after an attempt to read fails, so fgets() or fread() before.

Olivia answered 23/6, 2013 at 18:23 Comment(0)
F
6

Seeking beyond the EOF will enlarge the file after a subsequent write, so this is conformant, contrary to what others believe. See here: fseek

The fseek() function shall allow the file-position indicator to be set beyond the end of existing data in the file. If data is later written at this point, subsequent reads of data in the gap shall return bytes with the value 0 until data is actually written into the gap.

That's why fseek cannot return EOF. You will later get an EOF if you try to read from a position when nothing had been previously written to that position or behind. So this is all correct behavior.

Following answered 23/10, 2018 at 12:52 Comment(0)
G
3

Seeking beyond the end of the file on some operating systems increases the size of the file. As long as there's space to make the file larger, it will never return an error.

Gorgias answered 23/6, 2013 at 20:4 Comment(2)
Can you provide a reference?Landaulet
"Seeking beyond the end of the file on some operating systems increases the size of the file." I doubt this is in conformance with the C Standard.Louielouis

© 2022 - 2024 — McMap. All rights reserved.