// Resolve symlinks fs::path fs_base::canonicalize(fs::path in) { fs::path accum; if (!in.has_root_path()) { // dir is relative! accum = fs::system_complete("."); if (*--accum.end() == ".") accum = accum.parent_path(); } #ifdef WIN32 // No C:/ in the path else if (!in.has_root_name()) { accum = fs::system_complete(".").root_name() / accum; } #endif BOOST_FOREACH(fs::path seg, in) { if (seg == ".") continue; // We've already canon'd the path's parent, so just remove the last dir if (seg == "..") { accum = accum.parent_path(); continue; } accum /= seg; #ifndef WIN32 if (fs::is_symlink(accum)) { char buff[PATH_MAX]; ssize_t len = readlink(accum.string().c_str(), buff, PATH_MAX); if (len == -1) { format fmt = format(error_fmt) % "canonical" % std::strerror(errno) % accum; throw exception(fmt.str()); } fs::path link_path = std::string(buff, len); // An absolute link if (link_path.has_root_path()) accum = canonicalize(link_path); else { accum.remove_filename(); accum = canonicalize(accum / link_path); } } #endif } // This trickery forces a trailing / onto the dir if (fs::is_directory(accum)) { accum /= "."; accum.remove_filename(); } return accum; }