【问题标题】:create a unique temporary directory [duplicate]创建一个唯一的临时目录[重复]
【发布时间】:2018-10-21 07:22:30
【问题描述】:

我正在尝试在系统临时文件夹中创建一个唯一的临时目录,并且一直在阅读有关 tmpnam() 的安全性和文件创建问题的信息。

我编写了下面的代码,想知道它是否能满足这些问题,我对 tmpnam() 函数的使用是否正确以及是否抛出了 filesystem_error?我是否应该添加对其他内容的检查(例如 temp_directory_path,它也会引发异常)?

    // Unique temporary directory path in the system temporary directory path.
std::filesystem::path tmp_dir_path {std::filesystem::temp_directory_path() /= std::tmpnam(nullptr)};

// Attempt to create the directory.
if (std::filesystem::create_directories(tmp_dir_path)) {

    // Directory successfully created.
    return tmp_dir_path;

} else {

    // Directory could not be created.
    throw std::filesystem_error("directory could not be created.");

}

【问题讨论】:

    标签: c++ c++17


    【解决方案1】:

    来自cppreference.com

    虽然 std::tmpnam 生成的名称很难猜到,但在 std::tmpnam 返回和该程序尝试使用返回的名称之间,另一个进程可能会创建具有该名称的文件创建一个文件。

    问题不在于你如何使用它,而在于你使用它的事实。

    例如,在您的代码示例中,如果恶意用户成功猜测并在第一行和第二行之间创建了目录,它可能会拒绝您的应用程序的服务 (DOS),这可能很关键,也可能不是。

    相反,有一种方法可以在符合 POSIX 的系统上不进行竞争:

    • 有关文件,请参阅mkstemp(3) 了解更多信息
    • 有关目录,请参阅 mkdtemp(3) 了解更多信息。

    【讨论】:

      【解决方案2】:

      您的代码很好。因为您尝试创建目录,OS 将在您的进程和另一个尝试创建相同文件的进程之间进行仲裁,因此,如果您赢了,您拥有该文件,如果您输了,您会收到错误.

      我最近写了一个类似的函数。是否抛出异常取决于你想如何使用这个函数。例如,您可以简单地返回打开或关闭的 std::fstream 并使用 std::fstream::is_open 作为成功的衡量标准,或者在失败时返回空路径名。

      如果您不提供std::error_code 参数,查找std::filesystem::create_directories 它将抛出自己的异常,因此您不需要抛出自己的异常:

      std::filesystem::path tmp_dir_path {std::filesystem::temp_directory_path() /= std::tmpnam(nullptr)};
      
      // Attempt to create the directory.
      std::filesystem::create_directories(tmp_dir_path));
      
      // If that failed an exception will have been thrown
      // so no need to check or throw your own
      
      // Directory successfully created.
      return tmp_dir_path;
      

      【讨论】:

      • 感谢您的 cmets,我已尝试编译代码,当我抛出 filesystem_error 时,我打算包含一个 error_code 参数。我不完全确定我应该把什么作为这个异常的 error_code 参数。
      • 1.为什么 filesystem_error 需要 error_code? 2. 有没有办法只抛出没有错误代码的错误或者这是不好的做法?
      • @user1406186 尝试创建目录的调用会在失败时抛出自己的异常,因此您不需要这样做。鉴于此,我编辑了答案以显示与您的等效代码。
      • @user1406186 如果您不希望它抛出自己的异常,您需要为create_directories(path, std::error_code) 提供另一个参数。这样就可以得到错误码了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-01
      • 2022-09-08
      • 2022-11-25
      • 2013-09-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多