Example #1
0
// 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;
}