My program is recursively traversing a project directory, where circular symlinks may occur which raise an exception (too many levels of symbolic links) in another step of the algorithm. I'd like to find circular symlinks to avoid such exceptions. (Fixing the project by removing circular symlinks is not an option unfortunately.)
Is there a way to uncover circular symlinks using boost::filesystem
? I have already thought of resolving symlinks with read_symlink()
and continue it in a recursive way if a symlink resolves to another symlink but that's not exactly the optimal solution.
You should be able to use boost::filesystem::canonical
or weakly_canonical
(in case the file need not exist).
Note that there can be performance overhead with many symlinks with many path elements, because path elements are stat
-ed, building a new path instance.
#include <boost/filesystem.hpp>
#include <iostream>
int main(int argc, char** argv) {
using namespace boost::filesystem;
for (path link : std::vector(argv+1, argv+argc)) {
boost::system::error_code ec;
auto target = canonical(link, ec);
if (ec) {
std::cerr << link << " -> " << ec.message() << "\n";
} else {
std::cout << link << " -> " << target << "\n";
}
if (ec) {
target = weakly_canonical(link, ec);
if (!ec) {
std::cerr << " -- weakly: -> " << target << "\n";
}
}
}
}
When creating a few symlinks of various quality:
ln -sf main.cpp a
ln -sf b b
ln -sf d c
Incoking it with a b c d
:
"a" -> "/tmp/1613746951-1110913523/main.cpp"
"b" -> Too many levels of symbolic links
"c" -> No such file or directory
-- weakly: -> "c"
"d" -> No such file or directory
-- weakly: -> "d"