6

There seem to be many different ways to seek in C:

  • fseek()
  • fsetpos()
  • fseeko()
  • lseek()

And many seem to have *64() versions:

  • fseeko64()
  • lseek64()

To complicate matters further many seem to require macro definitions (like _LARGEFILE64_SOURCE or _GNU_SOURCE) to be available or to use 64-bit versions.

What is the easiest way to guarantee 64-bit IO using ANSI C on Windows, Linux, Mac, BSD, Solaris, etc., and since when has it been supported by each OS?

2 Answers2

0

Code works needs to employ at least 1 of the below restriction::

  1. long is 64-bit+, then use fseek().

  2. Only seek to locations that code has been to before as a result of fread(), fgets(), fscanf(), fgets(), and so use fgetpos(), fsetpos(). This is the best way if the file is a text file.

  3. Have access to a platform dependent 64-bit seek such as lseek64().

  4. Multiple 32-bit fseek().

  5. Use grossly inefficient code with rewind() and fgetc()/fread().

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • I'm not sure about multiple 32-bit fseek()'s and fgepos()/fsetpos() may not work either (most likely both kinds of positioning functions use the same type for position and call the same OS-specific function in the end). An OS-specific function/syscall is the best bet, although, clearly not portable. – Alexey Frunze Dec 21 '15 at 09:02
  • @Alexey Frunze `fgetpos()/fsetpos()` works as well on 64+ bit system as well as 32. `fseek()` pass 4G on 32 bit systems is more tenuous. A combo solution as you mentioned is best, using standard calls as able. – chux - Reinstate Monica Dec 22 '15 at 02:58
0

What is the easiest way to guarantee 64-bit IO using ANSI C on Windows, Linux, Mac, BSD, Solaris, etc.

The easiest way? Compile your code as a 64-bit executable. Be sure to use proper types, e.g. size_t is not an unsigned int - size_t is size_t. And hopefully, you're moved past ANSI C, as that generally refers to C89 and likely doesn't support 64-bit architectures well.

And as implied in the comments, there's no C Standard-compliant way to guarantee that you can easily get past 2GB. With a 64-bit binary, though, POSIX-compliant IO (open(),read(),write(), etc) would all work as size_t/ssize_t used by POSIX IO is 64-bit. POSIX also specifies fseeko() and ftello(), which are 64-bit compliant.

and since when has it been supported by each OS?

See here for details. Roughly, "full" 64-bit support dates to about the following times:

  • Solaris: 1998
  • Linux: 2003
  • Windows: 2006
  • OS X: 2007
Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • 1
    The `fseek()` function defined by standard C passes `offset` as `long`, though, and depending on the [data model](https://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models) (e.g. Windows uses LLP64), `long` may not be 64-bits; this is where the 2GiB limitation comes from (`LONG_MAX` must be at least (2^31)-1). –  Dec 21 '15 at 12:20
  • @oopaewem Thanks for pointing that out, but the OP did ask for the *easiest* way. In that case, you're back to the link from Lưu Vĩnh Phúc in his comment above (that there's no C Standard-compliant way): http://stackoverflow.com/questions/30657968/can-i-seek-a-position-beyond-2gb-in-c-using-the-standard-library. – Andrew Henle Dec 21 '15 at 12:34
  • I saw that link, and I suppose my OP is slightly misleading. By ANSI C I didn't mean I wanted to use exclusilevy ANSI C and no other (possibly platform dependent) libraries, I just meant to say I didn't want to use any C99 or C11 features, since Microsoft still doesn't have a complete C99 compiler (nor do they plan to). That said, C11 doesn't appear to have any standard way for seeking past 2GiB on an LLP64 data model either, so this is kind of a moot point. –  Dec 21 '15 at 12:44
  • @oopaewem POSIX seems to be the only standard that explicitly addresses 64-bit issues. http://www.unix.org/whitepapers/64bit.html – Andrew Henle Dec 21 '15 at 12:53