path.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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. inline bool operator!=(const TFsPath& that) const {
  52. return Path_ != that.Path_;
  53. }
  54. TFsPath& operator/=(const TFsPath& that);
  55. friend TFsPath operator/(const TFsPath& s, const TFsPath& p) {
  56. TFsPath ret(s);
  57. return ret /= p;
  58. }
  59. const TPathSplit& PathSplit() const;
  60. TFsPath& Fix();
  61. inline const TString& GetPath() const {
  62. return Path_;
  63. }
  64. /// last component of path, or "/" if root
  65. TString GetName() const;
  66. /**
  67. * "a.b.tmp" -> "tmp"
  68. * "a.tmp" -> "tmp"
  69. * ".tmp" -> ""
  70. */
  71. TString GetExtension() const;
  72. bool IsAbsolute() const;
  73. bool IsRelative() const;
  74. /**
  75. * TFsPath("/a/b").IsSubpathOf("/a") -> true
  76. *
  77. * TFsPath("/a").IsSubpathOf("/a") -> false
  78. *
  79. * TFsPath("/a").IsSubpathOf("/other/path") -> false
  80. * @param that - presumable parent path of this
  81. * @return True if this is a subpath of that and false otherwise.
  82. */
  83. bool IsSubpathOf(const TFsPath& that) const;
  84. /**
  85. * TFsPath("/a/b").IsNonStrictSubpathOf("/a") -> true
  86. *
  87. * TFsPath("/a").IsNonStrictSubpathOf("/a") -> true
  88. *
  89. * TFsPath("/a").IsNonStrictSubpathOf("/other/path") -> false
  90. * @param that - presumable parent path of this
  91. * @return True if this is a subpath of that or they are equivalent and false otherwise.
  92. */
  93. bool IsNonStrictSubpathOf(const TFsPath& that) const;
  94. bool IsContainerOf(const TFsPath& that) const {
  95. return that.IsSubpathOf(*this);
  96. }
  97. TFsPath RelativeTo(const TFsPath& root) const; // must be subpath of root
  98. /**
  99. * @returns relative path or empty path if root equals to this.
  100. */
  101. TFsPath RelativePath(const TFsPath& root) const; //..; for relative paths 1st component must be the same
  102. /**
  103. * Never fails. Returns this if already a root.
  104. */
  105. TFsPath Parent() const;
  106. TString Basename() const {
  107. return GetName();
  108. }
  109. TString Dirname() const {
  110. return Parent();
  111. }
  112. TFsPath Child(const TString& name) const;
  113. /**
  114. * @brief create this directory
  115. *
  116. * @param mode specifies permissions to use as described in mkdir(2), makes sense only on Unix-like systems.
  117. *
  118. * Nothing to do if dir exists.
  119. */
  120. void MkDir(const int mode = MODE0777) const;
  121. /**
  122. * @brief create this directory and all parent directories as needed
  123. *
  124. * @param mode specifies permissions to use as described in mkdir(2), makes sense only on Unix-like systems.
  125. */
  126. void MkDirs(const int mode = MODE0777) const;
  127. // XXX: rewrite to return iterator
  128. void List(TVector<TFsPath>& children) const;
  129. void ListNames(TVector<TString>& children) const;
  130. // Check, if path contains at least one component with a specific name.
  131. bool Contains(const TString& component) const;
  132. // fails to delete non-empty directory
  133. void DeleteIfExists() const;
  134. // delete recursively. Does nothing if not exists
  135. void ForceDelete() const;
  136. // XXX: ino
  137. inline bool Stat(TFileStat& stat) const {
  138. stat = TFileStat(Path_.data());
  139. return stat.Mode;
  140. }
  141. bool Exists() const;
  142. /// false if not exists
  143. bool IsDirectory() const;
  144. /// false if not exists
  145. bool IsFile() const;
  146. /// false if not exists
  147. bool IsSymlink() const;
  148. /// throw TIoException if not exists
  149. void CheckExists() const;
  150. void RenameTo(const TString& newPath) const;
  151. void RenameTo(const char* newPath) const;
  152. void RenameTo(const TFsPath& newFile) const;
  153. void ForceRenameTo(const TString& newPath) const;
  154. void CopyTo(const TString& newPath, bool force) const;
  155. void Touch() const;
  156. TFsPath RealPath() const;
  157. TFsPath RealLocation() const;
  158. TFsPath ReadLink() const;
  159. /// always absolute
  160. static TFsPath Cwd();
  161. inline void Swap(TFsPath& p) noexcept {
  162. DoSwap(Path_, p.Path_);
  163. Split_.Swap(p.Split_);
  164. }
  165. private:
  166. void InitSplit() const;
  167. TSplit& GetSplit() const;
  168. private:
  169. TString Path_;
  170. /// cache
  171. mutable TSimpleIntrusivePtr<TSplit> Split_;
  172. };
  173. namespace NPrivate {
  174. inline void AppendToFsPath(TFsPath&) {
  175. }
  176. template <class T, class... Ts>
  177. void AppendToFsPath(TFsPath& fsPath, const T& arg, Ts&&... args) {
  178. fsPath /= TFsPath(arg);
  179. AppendToFsPath(fsPath, std::forward<Ts>(args)...);
  180. }
  181. }
  182. template <class... Ts>
  183. TString JoinFsPaths(Ts&&... args) {
  184. TFsPath fsPath;
  185. ::NPrivate::AppendToFsPath(fsPath, std::forward<Ts>(args)...);
  186. return fsPath.GetPath();
  187. }