【问题标题】:c++ filesystem out of rootc ++文件系统出根目录
【发布时间】:2021-12-08 23:31:21
【问题描述】:

我试图在我的代码中捕获输入参数中的错误路径并发现了这种行为。 代码示例:

#include <iostream>
#include <filesystem>

using namespace std;
namespace fs = std::filesystem;

int main() {
  fs::path p = "/home";
  cout << p << endl;                        // "/home"
  cout << fs::exists(p) << endl;            // 1
  try {
    p = p / "../..";
    cout << p << endl;                      // "/home/../.."
    cout << fs::exists(p) << endl;          // 1
  } catch (...) {
    cout << "catched" << endl;
  }
  p = fs::canonical(p);
  cout << p << endl;                        // "/"
  cout << fs::exists(p) << endl;            // 1
  return 0;
}

如何使用标准功能捕获超出根目录的范围?这是错误还是功能?

【问题讨论】:

  • /.. 是 linux 和 windows 上的有效路径,它与只是 /
  • 这是一项功能。所有超过 root 的尝试都会被忽略。这就是 FS 的工作原理,并不特定于 C++。
  • 您可以通过运行ls -ai / 来简单地检查这一点。你看到/./.. 有相同的inode 号了吗?
  • 试试这个简单的实验:启动一个终端/命令提示符/shell/任何你想调用它。输入以下命令,看看 shell 如何处理“超出根目录”。 cd /homecd /home/../.. 你的程序的行为是否应该不同于标准实用程序的行为?

标签: c++ boost boost-filesystem


【解决方案1】:

就像其他人所说的那样,您不能“越界”使用相对父目录 (..)。

也就是说,你可以 check the depth of a given path:

路径可以通过 begin() 和 end() 函数返回的迭代器逐元素遍历,它以通用格式查看路径并迭代根名称、根目录和后续文件名元素(目录分隔符被跳过,除了标识根目录的那个)。如果路径中的最后一个元素是目录分隔符,则最后一个迭代器将取消对空元素的引用。

Live On Coliru

#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main()
{
    std::cout << std::boolalpha;
    for (fs::path p :
         {
             "/home",
             "/home/sehe",
             "/home/",
             "//home/",
             "/home/sehe/",
         }) //
    {
        try {
            p = canonical(absolute(p));

            std::cout << " -- " << p << " (" << exists(p) << ")\n";

            std::cout << "elements:";
            for (auto& el : p) {
                std::cout << " " << el << ";";
            }
            std::cout << "\n";

            if (std::distance(p.begin(), p.end()) < 3) {
                std::cout << "Does not have two unique parents\n";
            } else {
                p = p / "../..";
                std::cout << "Up two: " << p << " (" << exists(p) << ")\n";
            }
        } catch (std::exception const& e) {
            std::cout << "error " << e.what() << "\n";
        }
    }
}

在我的机器上打印:

 -- "/home" (true)
elements: "/"; "home";
Does not have two unique parents
 -- "/home/sehe" (true)
elements: "/"; "home"; "sehe";
Up two: "/home/sehe/../.." (true)
 -- "/home" (true)
elements: "/"; "home";
Does not have two unique parents
 -- "/home" (true)
elements: "/"; "home";
Does not have two unique parents
 -- "/home/sehe" (true)
elements: "/"; "home"; "sehe";
Up two: "/home/sehe/../.." (true)

【讨论】:

    猜你喜欢
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    相关资源
    最近更新 更多