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

时间:2015-01-18 12:44:42

标签: c 32bit-64bit glibc fseek large-file-support

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

我做了以下改动:

  1. CFLAGS += -D_FILE_OFFSET_BITS=64添加到makefile。
  2. 我通过调用fseek()将呼叫替换为fseeko()(我还需要MSVC6支持,但一次只需一步)。
  3. 我已将第二个参数的类型更改为off_t。变量sizeof()返回8.
  4. 这是一个很好的样本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

2 个答案:

答案 0 :(得分:1)

示例中的1 << 32是未定义的行为。它可能会返回0或1.确保在移动之前将1转换为合适的类型。如果unsigned long也有32位,则1UL << 32以同样的方式出错。

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

答案 1 :(得分:0)

以下程序,编译用 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;
}