c++ filesystem out of root

144 Views Asked by At

I`l trying to catch wrong paths in input args in my code and found that behavior. code example:

#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;
}

How to catch out of bounds of the root with the standard capabilities? Is this a bug or a feature?

1

There are 1 best solutions below

0
sehe On

Like everyone else said, you cannot "go out of bounds" with relative parent directory (..).

That said, you can check the depth of a given path:

The path can be traversed element-wise via iterators returned by the begin() and end() functions, which views the path in generic format and iterates over root name, root directory, and the subsequent file name elements (directory separators are skipped except the one that identifies the root directory). If the very last element in the path is a directory separator, the last iterator will dereference to an empty element.

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";
        }
    }
}

On my machine prints:

 -- "/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)