path.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. #pragma once
  2. #include "fwd.h"
  3. #include "pathsplit.h"
  4. #include <util/generic/ptr.h>
  5. #include <util/generic/strbuf.h>
  6. #include <util/generic/string.h>
  7. #include <util/generic/vector.h>
  8. #include <util/string/cast.h>
  9. #include <util/system/fstat.h>
  10. #include <util/system/platform.h>
  11. #include <util/system/sysstat.h>
  12. #include <util/system/yassert.h>
  13. #include <utility>
  14. /**
  15. * Class behaviour is platform-dependent.
  16. * It uses platform-dependent separators for path-reconstructing operations.
  17. */
  18. class TFsPath {
  19. private:
  20. struct TSplit;
  21. public:
  22. TFsPath();
  23. TFsPath(const TString& path);
  24. TFsPath(const TStringBuf path);
  25. TFsPath(const char* path);
  26. TFsPath(const std::string& path)
  27. : TFsPath(TStringBuf(path))
  28. {
  29. }
  30. TFsPath(const TFsPath& that);
  31. TFsPath(TFsPath&& that);
  32. TFsPath& operator=(const TFsPath& that);
  33. TFsPath& operator=(TFsPath&& that);
  34. ~TFsPath() = default;
  35. void CheckDefined() const;
  36. inline bool IsDefined() const {
  37. return Path_.length() > 0;
  38. }
  39. inline explicit operator bool() const {
  40. return IsDefined();
  41. }
  42. inline const char* c_str() const {
  43. return Path_.c_str();
  44. }
  45. inline operator const TString&() const {
  46. return Path_;
  47. }
  48. inline bool operator==(const TFsPath& that) const {
  49. return Path_ == that.Path_;
  50. }
  51. TFsPath& operator/=(const TFsPath& that);
  52. friend TFsPath operator/(const TFsPath& s, const TFsPath& p) {
  53. TFsPath ret(s);
  54. return ret /= p;
  55. }
  56. const TPathSplit& PathSplit() const;
  57. TFsPath& Fix();
  58. inline const TString& GetPath() const {
  59. return Path_;
  60. }
  61. /// last component of path, or "/" if root
  62. TString GetName() const;
  63. /**
  64. * "a.b.tmp" -> "tmp"
  65. * "a.tmp" -> "tmp"
  66. * ".tmp" -> ""
  67. */
  68. TString GetExtension() const;
  69. bool IsAbsolute() const;
  70. bool IsRelative() const;
  71. /**
  72. * TFsPath("/a/b").IsSubpathOf("/a") -> true
  73. *
  74. * TFsPath("/a").IsSubpathOf("/a") -> false
  75. *
  76. * TFsPath("/a").IsSubpathOf("/other/path") -> false
  77. * @param that - presumable parent path of this
  78. * @return True if this is a subpath of that and false otherwise.
  79. */
  80. bool IsSubpathOf(const TFsPath& that) const;
  81. /**
  82. * TFsPath("/a/b").IsNonStrictSubpathOf("/a") -> true
  83. *
  84. * TFsPath("/a").IsNonStrictSubpathOf("/a") -> true
  85. *
  86. * TFsPath("/a").IsNonStrictSubpathOf("/other/path") -> false
  87. * @param that - presumable parent path of this
  88. * @return True if this is a subpath of that or they are equivalent and false otherwise.
  89. */
  90. bool IsNonStrictSubpathOf(const TFsPath& that) const;
  91. bool IsContainerOf(const TFsPath& that) const {
  92. return that.IsSubpathOf(*this);
  93. }
  94. TFsPath RelativeTo(const TFsPath& root) const; // must be subpath of root
  95. /**
  96. * @returns relative path or empty path if root equals to this.
  97. */
  98. TFsPath RelativePath(const TFsPath& root) const; //..; for relative paths 1st component must be the same
  99. /**
  100. * Never fails. Returns this if already a root.
  101. */
  102. TFsPath Parent() const;
  103. TString Basename() const {
  104. return GetName();
  105. }
  106. TString Dirname() const {
  107. return Parent();
  108. }
  109. TFsPath Child(const TString& name) const;
  110. /**
  111. * @brief create this directory
  112. *
  113. * @param mode specifies permissions to use as described in mkdir(2), makes sense only on Unix-like systems.
  114. *
  115. * Nothing to do if dir exists.
  116. */
  117. void MkDir(const int mode = MODE0777) const;
  118. /**
  119. * @brief create this directory and all parent directories as needed
  120. *
  121. * @param mode specifies permissions to use as described in mkdir(2), makes sense only on Unix-like systems.
  122. */
  123. void MkDirs(const int mode = MODE0777) const;
  124. // XXX: rewrite to return iterator
  125. void List(TVector<TFsPath>& children) const;
  126. void ListNames(TVector<TString>& children) const;
  127. // Check, if path contains at least one component with a specific name.
  128. bool Contains(const TString& component) const;
  129. // fails to delete non-empty directory
  130. void DeleteIfExists() const;
  131. // delete recursively. Does nothing if not exists
  132. void ForceDelete() const;
  133. // XXX: ino
  134. inline bool Stat(TFileStat& stat) const {
  135. stat = TFileStat(Path_.data());
  136. return stat.Mode;
  137. }
  138. bool Exists() const;
  139. /// false if not exists
  140. bool IsDirectory() const;
  141. /// false if not exists
  142. bool IsFile() const;
  143. /// false if not exists
  144. bool IsSymlink() const;
  145. /// throw TIoException if not exists
  146. void CheckExists() const;
  147. void RenameTo(const TString& newPath) const;
  148. void RenameTo(const char* newPath) const;
  149. void RenameTo(const TFsPath& newFile) const;
  150. void ForceRenameTo(const TString& newPath) const;
  151. void CopyTo(const TString& newPath, bool force) const;
  152. void Touch() const;
  153. TFsPath RealPath() const;
  154. TFsPath RealLocation() const;
  155. TFsPath ReadLink() const;
  156. /// always absolute
  157. static TFsPath Cwd();
  158. inline void Swap(TFsPath& p) noexcept {
  159. DoSwap(Path_, p.Path_);
  160. Split_.Swap(p.Split_);
  161. }
  162. private:
  163. void InitSplit() const;
  164. TSplit& GetSplit() const;
  165. private:
  166. TString Path_;
  167. /// cache
  168. mutable TSimpleIntrusivePtr<TSplit> Split_;
  169. };
  170. namespace NPrivate {
  171. inline void AppendToFsPath(TFsPath&) {
  172. }
  173. template <class T, class... Ts>
  174. void AppendToFsPath(TFsPath& fsPath, const T& arg, Ts&&... args) {
  175. fsPath /= TFsPath(arg);
  176. AppendToFsPath(fsPath, std::forward<Ts>(args)...);
  177. }
  178. } // namespace NPrivate
  179. template <class... Ts>
  180. TString JoinFsPaths(Ts&&... args) {
  181. TFsPath fsPath;
  182. ::NPrivate::AppendToFsPath(fsPath, std::forward<Ts>(args)...);
  183. return fsPath.GetPath();
  184. }