为什么我不能“freopen”一个“tmpfile”?

时间:2013-11-23 21:43:04

标签: c docker temporary-files

我尝试编译并运行具有以下行的C代码:

FILE *preproc_producer = NULL;
preproc_producer = tmpfile();
// preproc_producer is not NULL here
preproc_producer = freopen(NULL, "r+", preproc_producer);
// preproc_producer is NULL here

但是,在运行代码时,preproc_producer结束NULL,错误代码为Stale NFS file handle

  1. 上述代码有什么问题?

  2. 此处freopen来电的目的是什么?我评论了freopen行,其余程序似乎正在运作。

  3. 我正在使用GCC 4.7.2,在Docker 0.6.7 Linux容器中运行Ubuntu 64 12.04。上面的代码似乎在Docker容器之外工作。

    更新: strace dump:

    stat("/tmp", {st_mode=S_IFDIR|S_ISVTX|0777, st_size=4096, ...}) = 0
    gettimeofday({1385247432, 199732}, NULL) = 0
    getpid()                                = 127
    open("/tmp/tmpf9l14HD", O_RDWR|O_CREAT|O_EXCL, 0600) = 3
    unlink("/tmp/tmpf9l14HD")               = 0
    fcntl(3, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
    brk(0)                                  = 0xc94000
    brk(0xcb5000)                           = 0xcb5000
    fstat(3, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
    mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7afb9d0000
    lseek(3, 0, SEEK_CUR)                   = 0
    lstat("/proc/self/fd/3", {st_mode=S_IFLNK|0700, st_size=64, ...}) = 0
    munmap(0x7f7afb9d0000, 4096)            = 0
    open("/proc/self/fd/3", O_RDWR)         = -1 ESTALE (Stale NFS file handle)
    

1 个答案:

答案 0 :(得分:3)

来自C99标准:

  

freopen函数打开文件,其名称是filename指向的字符串   并将流指向的流与它相关联。 mode参数仅用于   就像在fopen函数中一样。

     

如果filename是空指针,则freopen函数会尝试更改模式   由模式指定的流,就好像当前与之关联的文件的名称一样   流已被使用。它是实现定义的模式的变化   允许(如果有的话),以及在什么情况下。

所以,编写此代码的人可能会将临时文件打开模式从w+b更改为r+(这主要归结为将流更改为文本模式)。不幸的是,似乎在您的实现中,不可能以这种方式更改临时文件的打开模式。

我认为这可能是因为关闭临时文件也会删除它,但也可能glibc freopen的{​​{1}}实现不支持freopen中的模式更改(该联机帮助页甚至没有提到将NULL作为第一个参数传递的可能性。)