关闭文件的文件号

fileno for closed file

我有一个这样的函数,旨在读取一个文件:

int foo(FILE* f)

我想用flock来防止TOCTTOU。 flock 需要一个整数形式的文件描述符。我可以使用 fileno(file) 得到这个。因此 foo 的实现可能如下所示:

int foo(FILE* f) {
  if(!f) return -1;
  int fd = fileno(f);
  if(fd < 0) return -1;
  flock(fd, LOCK_EX);
  //do all the reading stuff and so on.
} 

然而,恶意用户可能会做这样的事情:

FILE* test;
test = fopen("someexistingfile.txt", "r");
fclose(test);
foo(test);

然后我遇到了一个问题,因为 fileno 会根据 valgrind 进行无效读取,因为它假定文件是打开的。

关于如何检查文件是否已关闭的任何想法?

C11 n1570 7.21.3p4

  1. A file may be disassociated from a controlling stream by closing the file. Output streams are flushed (any unwritten buffer contents are transmitted to the host environment) before the stream is disassociated from the file. The value of a pointer to a FILE object is indeterminate after the associated file is closed (including the standard text streams). Whether a file of zero length (on which no characters have been written by an output stream) actually exists is implementation-defined.

fclose 之后,在库函数中使用 FILE * 的值会导致未定义的行为。在重新分配之前,指针的值根本不能安全地用于任何事情。

换句话说,您实际上根本无法做任何事情来辨别您提供的FILE *值是否指的是有效的打开文件.. . 除了针对 NULL 进行测试 - 如果指针的值为 NULL 它肯定不能指向打开的流。