簡體   English   中英

安全使用std :: tmpnam

[英]Safe use of std::tmpnam

因此,我正在開發一個應用程序,它需要創建一個文件,寫入其中,使用該文件作為輸入來調用另一個程序,然后刪除該文件。

我尋找了可能的解決方案,一個解決方案看起來像這樣。

std::FILE* tmpf = std::tmpfile();
std::fputs("Hello, world", tmpf);

根據std::tmpfile的文檔,如果手動關閉了文件,或者程序以自然方式退出,則該文件將被刪除。 這看起來是個好的解決方案,但有一個例外。 看起來很亂(使用CI / O而不是C ++流)。

另一個解決方案是使用std::tmpnam ,它將生成唯一的文件名。

std::string file_name = std::tmpname(NULL);
// (*)
std::fstream stream{file_name};
stream << "Hello World" << std::endl;

但是這個也有問題。 如果另一個程序創建的文件具有相同的名稱,而我的程序位於(*) ,則我們都將對同一文件執行操作,這當然是我要避免的事情。

C ++ STL(仍然)不支持文件系統操作,例如檢查文件是否存在。 我可以使用stat東西進行檢查,但是由於檢查文件並創建它不是原子的,因此它無法解決任何問題。 而且我沒有找到原子操作的C ++ STL方法,該方法將:檢查文件是否存在,如果不存在,則將其打開,如果是,則失敗。

所以,我的問題是,解決這個問題的正確方法是什么? 我錯過了什么?

這是我幾乎沒有混亂的解決方案:

#include <cstdio>
#include <iostream>
#include <string>
#include <ext/stdio_filebuf.h> // libstdc++ specific

int main()
{
    __gnu_cxx::stdio_filebuf<char> tmpfile_buf{std::tmpfile(), std::ios::in | std::ios::out | std::ios::binary};
    std::iostream tmpstream{&tmpfile_buf};

    // write in stream
    tmpstream << "Hello World" << std::endl;
    tmpstream.seekg(0);

    // read from stream
    std::string str;
    std::getline(tmpstream, str);
    std::cout << str << std::endl;
}

現場例子

std::tmpfile()並從具有基礎FILE*的緩沖區構建流。 這是GNU擴展,因此不可移植:(。

您的規范“ ...創建文件,寫入文件,使用該文件作為輸入來調用另一個程序,然后刪除該文件。” 與tmpfile()不兼容。 一方面,沒有(便攜式)方法可以從您從tmpfile()獲得的FILE指針中獲取文件名,其次,在POSIX平台上,tmpfile()通常會從目錄中刪除文件,然后再從tmpfile()返回(如果您不熟悉POSIX文件系統的語義,只要您的進程具有打開的文件描述符(即使從目錄中刪除該文件),該文件就存在,這意味着無法從文件系統訪問它。

鑒於此,您將必須使用某種tmpname()類型的方法,並找出一種防止兩個進程同時訪問它的方法(文件鎖,使用stat()檢查鏈接數等)。

或者更好的是,不要使用文件進行進程間通信。 對於最簡單的情況(?),請在父級中創建一個管道,然后將其連接到子級的stdin。

我可能有建議的Boost解決方案,但是我不能在這里進行測試。

使用從std::tmpfile()返回的FILE* ,可以獲取文件描述符:

#include <cstdio>
FILE* const tmpfile = std::tmpfile();
const int fd = ::fileno(tmpfile);

在這個階段,使用boost::iostreams::file_descriptor_source看起來一切都很好:

#include <boost/iostreams/code_converter.hpp>
#include <boost/iostreams/maped_file.hpp>
file_descriptor_source tmpstream(fd, boost::iostreams::close_handle);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM