Why does fseeko() fail with EINVAL?

261 views Asked by At

I need to add LFS to a C process which uses fseek(). gcc and glibc are of version 3.2.3 and 2.5, respectively.

I made the following alterations:

  1. added CFLAGS += -D_FILE_OFFSET_BITS=64 to the makefile.
  2. I replaced the call to fseek() with a call to fseeko() (I also need MSVC6 support, but one step at a time).
  3. I've changed the 2nd argument's type to off_t. sizeof() on the variable returns 8.

Here is as good a sample main() as I can get past our DLP and its output:

fd = fopen("large_file", "rb");
off_t offset = 1ULL << 32;
rc = fseeko(fd, offset, SEEK_SET);

rc = -1 sizeof(offset)=8 errno=22 offset=2147483648

2

There are 2 answers

1
wildplasser On BEST ANSWER

The below program, compiled with CFLAGS = -g2 -Wall -D_LARGEFILE64_SOURCE works here (3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux)

(compiling with CFLAGS = -g2 -Wall -D_FILE_OFFSET_BITS=64 and s/off64_t/off_t/ works equally well)

#include <stdio.h>
#include <strings.h>
#include <unistd.h>

int main(void)
{
off64_t offset ;
int rc;
FILE *fp;

fp = fopen("testfile", "r+b");
if (!fp) {
        perror("fopen" );
        return 1;
        }

offset = 1ull << 32;
rc = fseeko(fp, offset, 0);
if (rc < 0) {
        perror("fseeko" );
        return 2;
        }
rc = fwrite( "OMG!", 4, 1, fp);
fprintf(stderr,"Write(4) : %d\n", rc);

fclose(fp);

return 0;
}
1
jilles On

The 1 << 32 in your example is undefined behaviour. It is likely to return 0 or 1. Make sure to convert the 1 to a suitable type before shifting it. If unsigned long has 32 bits as well, then 1UL << 32 is wrong in the same way.

Avoid -D_LARGEFILE64_SOURCE and off64_t, since they just make things more complicated. Instead, use only -D_FILE_OFFSET_BITS=64 and use off_t which should then be 64 bits.