为什么 fseeko() 会因 EINVAL 而失败?

Why does fseeko() fail with EINVAL?

我需要将 LFS 添加到使用 fseek() 的 C 进程中。 gcc和glibc分别是3.2.3和2.5版本。

我做了以下改动:

  1. 添加 CFLAGS += -D_FILE_OFFSET_BITS=64 到 makefile。
  2. 我将对 fseek() 的调用替换为对 fseeko() 的调用(我还需要 MSVC6 支持,但一次一个步骤)。
  3. 我已将第二个参数的类型更改为 off_tsizeof() 变量 returns 8.

这是一个很好的示例 main() 我可以通过我们的 DLP 及其输出:

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

您示例中的 1 << 32 是未定义的行为。很可能 return 0 或 1。确保在移位之前将 1 转换为合适的类型。如果 unsigned long 也有 32 位,那么 1UL << 32 也是错误的。

避免使用 -D_LARGEFILE64_SOURCEoff64_t,因为它们只会让事情变得更复杂。相反,仅使用 -D_FILE_OFFSET_BITS=64 并使用 off_t,这应该是 64 位。

下面的程序,用 CFLAGS = -g2 -Wall -D_LARGEFILE64_SOURCE 在这里工作(3.13.0-43-generic #72-Ubuntu SMP Mon Dec 8 19:35:06 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux)

(使用 CFLAGS = -g2 -Wall -D_FILE_OFFSET_BITS=64s/off64_t/off_t/ 编译同样有效)

#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;
}