为什么 POSIX 允许在现有文件结尾 (fseek) 之外寻找只读模式

Why POSIX allows seeking beyond the existing end of file (fseek) for read only mode

为什么查找文件末尾会有用?为什么 POSIX 允许像示例中那样在以只读方式打开的文件中查找?

C++:http://en.cppreference.com/w/c/io/fseek posix: https://www.unix.com/man-page/posix/3P/fseek/

我在 MinGW-64w 上测试的下一个代码

#include <cassert>
#include <cstdio>
#include <cstring>

int main() {
  std::FILE* f = std::fopen("tmp_file.txt", "wb");
  auto result = std::fwrite("1", 1, 1, f);
  assert(result == 1);
  result = std::fclose(f);
  assert(result == 0);

  f = std::fopen("tmp_file.txt", "rb");  // READ ONLY binary mode
  result = std::fseek(f, 100500, SEEK_SET);
  assert(result == 0);  // WHY I can seek to not existing position in file?
                        // opended in READ_ONLY mode?
  char buff[100500] = {0};
  result = std::fread(&buff, sizeof(buff), 1, f);
  printf("result = %zu, errno: %s ferror(f): %d feof(f): %d", result,
         std::strerror(errno), std::ferror(f), std::feof(f) != 0);

  return result;
}

Why seek over end of file can be usefull?

它是否有用一般取决于实现。 C 和 C++ 没有指定这样的操作必须成功,尽管 POSIX 确实如此,正如您似乎知道的那样。然而,即使在非 POSIX C 中,

If a read or write error occurs [within fseek], the error indicator for the stream is set and fseek fails

(C2011 7.21.9.2/2),以及

a successful call to the fseek function undoes any effects of the ungetc function on the stream, clears the end-of-file indicator for the stream

(C2011 7.21.9.2/5)。即使 fseek 使文件处于奇怪(但有效)状态,这些副作用也可能是可取的。尽管如此,你的问题

Why POSIX let to seek like in example in file opened for read only?

建议您认为 fseek 应该失败,否则会将(只读)文件定位在无法读取数据的位置。但为什么要为此特例呢?一个以读写方式打开的文件可以(根据 POSIX)定位到它的末尾之后,然后读取它与读取类似定位的只读文件没有特别不同。

使 fseek 的行为在所有可搜索文件中保持一致,其价值超出您的想象。

如您所知,在可写文件的末尾之外寻找,然后写入,扩展了文件。我想你的问题是你不想扩展一个只为阅读而打开的文件,因为扩展是一种修改。

但是仅仅在可写文件的末尾之外寻找并不能扩展它——它是在寻找然后写入。求刚设置read/write点。

因此在读取时寻找文件末尾设置读取点,这只是数据结构中的一个数字,所以我想没有人担心检查它的有效性。如果您在可读文件的末尾之外搜索然后尝试写入,则会出现错误 ("file not open for writing"),如果您在可读文件的末尾之外搜索然后读取,您只会得到 EOF。在这两种情况下,您都不会扩展或以其他方式更改文件。

(您可能还想知道,如果您在某个其他进程正在写入的可读文件的结尾之外进行查找,然后其他进程向 "fill in" 写入更多内容,直到您查找的位置到,然后然后你试试看?这是一个有趣的问题。我怀疑它会起作用,但我还没有试过。)