cmPathResolver.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #pragma once
  4. #include "cmConfigure.h" // IWYU pragma: keep
  5. #include <string>
  6. #include "cmsys/Status.hxx"
  7. namespace cm {
  8. namespace PathResolver {
  9. class System;
  10. /** Normalize filesystem paths according to a Policy.
  11. *
  12. * Resolved paths are always absolute, have no '..', '.', or empty
  13. * components, and have a trailing '/' if and only if the entire
  14. * path is a root component.
  15. *
  16. * The Policy determines behavior w.r.t. symbolic links, existence,
  17. * and matching the on-disk case (upper/lower) of existing paths.
  18. */
  19. template <class Policy>
  20. class Resolver
  21. {
  22. System& OS;
  23. public:
  24. /** Construct with a concrete filesystem access implementation. */
  25. Resolver(System& os);
  26. /** Resolve the input path according to the Policy, if possible.
  27. On success, the resolved path is stored in 'out'.
  28. On failure, the non-existent path is stored in 'out'. */
  29. cmsys::Status Resolve(std::string in, std::string& out) const;
  30. };
  31. /** Access the filesystem via runtime dispatch.
  32. This allows unit tests to work without accessing a real filesystem,
  33. which is particularly important on Windows where symbolic links
  34. may not be something we can create without administrator privileges.
  35. */
  36. class System
  37. {
  38. public:
  39. System();
  40. virtual ~System() = 0;
  41. /** If the given path is a symbolic link, read its target.
  42. If the path exists but is not a symbolic link, fail
  43. with EINVAL or ERROR_NOT_A_REPARSE_POINT. */
  44. virtual cmsys::Status ReadSymlink(std::string const& path,
  45. std::string& symlink_target) = 0;
  46. /** Return whether the given path exists on disk. */
  47. virtual bool PathExists(std::string const& path) = 0;
  48. /** Get the process's working directory. */
  49. virtual std::string GetWorkingDirectory() = 0;
  50. #ifdef _WIN32
  51. /** Get the process's working directory on a Windows drive letter.
  52. This is a legacy DOS concept supported by 'cmd' shells. */
  53. virtual std::string GetWorkingDirectoryOnDrive(char drive_letter) = 0;
  54. #endif
  55. #if defined(_WIN32) || defined(__APPLE__)
  56. /** Read the on-disk spelling of the last component of a file path. */
  57. virtual cmsys::Status ReadName(std::string const& path,
  58. std::string& name) = 0;
  59. #endif
  60. };
  61. namespace Policies {
  62. // IWYU pragma: begin_exports
  63. /** Normalizes paths while resolving symlinks only when followed
  64. by '..' components. Does not require paths to exist, but
  65. reads on-disk case of paths that do exist (on Windows). */
  66. struct LogicalPath;
  67. /** Normalizes paths while resolving all symlinks.
  68. Requires paths to exist, and reads their on-disk case (on Windows). */
  69. struct RealPath;
  70. /** Normalizes paths in memory without disk access.
  71. Assumes components followed by '..' components are not symlinks. */
  72. struct NaivePath;
  73. // IWYU pragma: end_exports
  74. }
  75. extern template class Resolver<Policies::LogicalPath>;
  76. extern template class Resolver<Policies::RealPath>;
  77. extern template class Resolver<Policies::NaivePath>;
  78. }
  79. }