filesystem.h 69 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_COMMON_FILESYSTEM_H_
  5. #define CARBON_COMMON_FILESYSTEM_H_
  6. #include <dirent.h>
  7. #include <fcntl.h>
  8. #include <sys/file.h>
  9. #include <sys/stat.h>
  10. #include <sys/types.h>
  11. #include <unistd.h>
  12. #include <chrono>
  13. #include <concepts>
  14. #include <filesystem>
  15. #include <iterator>
  16. #include <string>
  17. #include "common/check.h"
  18. #include "common/error.h"
  19. #include "common/ostream.h"
  20. #include "common/raw_string_ostream.h"
  21. #include "common/template_string.h"
  22. #include "llvm/ADT/ScopeExit.h"
  23. #include "llvm/ADT/StringRef.h"
  24. #include "llvm/Support/FormatVariadic.h"
  25. // Provides a filesystem library for use in the Carbon project.
  26. //
  27. // This library provides an API designed to support modern Unix / Linux / POSIX
  28. // style filesystem operations, often called "Unix-like"[1] here, efficiently
  29. // and securely, while also carefully staying to a set of abstractions and
  30. // operations that can be reasonably implemented even on Windows platforms.
  31. //
  32. // TODO: Currently, there is not a Windows implementation, but this is actively
  33. // desired when we have testing infrastructure in place for Windows development.
  34. // Lacking that testing infrastructure and a full Windows port, the operations
  35. // here are manually compared with LLVM's filesystem library to ensure a
  36. // reasonable Windows implementation is possible.
  37. //
  38. // The library uses C++'s `std::filesystem::path` as its abstraction for
  39. // paths. This library provides two core APIs: open directories and files.
  40. //
  41. // Open directories provide relative- and absolute-path based operations to open
  42. // other directories or files. This allows secure creation of directories even
  43. // in the face of adversarial operations for example in a shared `/tmp`
  44. // directory. There is a `constexpr` current working directory available as
  45. // `Cwd()` that models normal filesystem operations with paths.
  46. //
  47. // Open files provide read, write, and other operations on the file. There are
  48. // separate types for read-only, write-only, and read-write files to model the
  49. // different APIs available.
  50. //
  51. // The APIs for both directories and files are primarily on `*Ref` types that
  52. // model a non-owning reference to the directory or file. These types are the
  53. // preferred types to use on an API boundary. Owning versions are provided that
  54. // ensure the file or directory is closed on destruction. Files support explicit
  55. // closing in order to observe any close-specific errors.
  56. //
  57. // Where APIs require flag parameters of some form, this library provides
  58. // enumerations that model those flags. The enumeration values are in turn
  59. // chosen to simplify passing these to specific native APIs. This means the
  60. // enumeration *values* should not be expected to be portable across platforms.
  61. // Customizing the values is part of the larger TODO to port the implementation
  62. // to Windows.
  63. //
  64. // [1]: Note that we refer to platforms as "Unix-like" rather than POSIX as we
  65. // want to group together all the OSes where the Unix-derived APIs are the
  66. // primary and expected way to interact with the filesystem, regardless of
  67. // whether a POSIX conforming API happens to exist. For example, both macOS
  68. // and WSL (Windows Subsystem for Linux) _are_ Unix-like as those are the
  69. // primary APIs used to access files in those environments. But Windows
  70. // itself _isn't_ Unix-like, even considering things like the defunct NT
  71. // POSIX subsystem or modern WSL, as those aren't the primary filesystem
  72. // APIs for the (non-WSL) Windows platform. This also matches the rough OS
  73. // classification used in LLVM.
  74. namespace Carbon::Filesystem {
  75. // The different creation options available when opening a file or directory.
  76. //
  77. // Because these are by far the most common parameters and they have unambiguous
  78. // names, the enumerators are also available directly within the namespace.
  79. enum class CreationOptions {
  80. // Requires an existing file or directory.
  81. OpenExisting = 0,
  82. // Opens an existing file or directory, and create one otherwise.
  83. OpenAlways = O_CREAT,
  84. // Opens and truncates an existing file or creates a new file. Provides
  85. // consistent behavior of an empty file regardless of the starting state. This
  86. // cannot be used for directories as they cannot be truncated on open. This is
  87. // essentially a short-cut for using `OpenAlways` and passing the
  88. // `OpenFlags::Truncate` below.
  89. CreateAlways = O_CREAT | O_TRUNC,
  90. // Requires no existing file or directory and will error if one is found. Only
  91. // succeeds when it creates a new file or directory.
  92. CreateNew = O_CREAT | O_EXCL,
  93. };
  94. using enum CreationOptions;
  95. // General flags to control the behavior of opening files that aren't covered by
  96. // other more specific flags.
  97. //
  98. // These can be combined using the `|` operator where the semantics are
  99. // compatible, although not all are.
  100. enum class OpenFlags : int {
  101. None = 0,
  102. // Open the file for appending rather than with the position at the start.
  103. //
  104. // An error to combine with `Truncate` or to use with `CreateAlways`.
  105. Append = O_APPEND,
  106. // Open the file and truncate its contents to be empty.
  107. Truncate = O_TRUNC,
  108. // Don't follow a symlink in the final path component being opened.
  109. NoFollow = O_NOFOLLOW,
  110. };
  111. inline auto operator|(OpenFlags lhs, OpenFlags rhs) -> OpenFlags {
  112. return static_cast<OpenFlags>(static_cast<int>(lhs) | static_cast<int>(rhs));
  113. }
  114. inline auto operator|=(OpenFlags& lhs, OpenFlags rhs) -> OpenFlags& {
  115. lhs = lhs | rhs;
  116. return lhs;
  117. }
  118. // Flags controlling which permissions should be checked in an `Access` call.
  119. //
  120. // These permissions can also be combined with the `|` operator, so
  121. // `AccessCheckFlags::Read | AccessCheckFlags::Write` checks for both read and
  122. // write access.
  123. enum class AccessCheckFlags : int {
  124. Exists = F_OK,
  125. Read = R_OK,
  126. Write = W_OK,
  127. Execute = X_OK,
  128. };
  129. inline auto operator|(AccessCheckFlags lhs, AccessCheckFlags rhs)
  130. -> AccessCheckFlags {
  131. return static_cast<AccessCheckFlags>(static_cast<int>(lhs) |
  132. static_cast<int>(rhs));
  133. }
  134. inline auto operator|=(AccessCheckFlags& lhs, AccessCheckFlags rhs)
  135. -> AccessCheckFlags& {
  136. lhs = lhs | rhs;
  137. return lhs;
  138. }
  139. // The underlying integer type that should be used to model the mode of a file.
  140. //
  141. // The mode is used in this API to represent both the permission bit mask and
  142. // special properties of a file. For example, on Unix-like systems, it combines
  143. // permissions with set-user-ID, set-group-ID, and sticky bits.
  144. //
  145. // The permission bits in the mode are represented using the Unix-style bit
  146. // pattern that facilitates octal modeling:
  147. // - Owner bit mask: 0700
  148. // - Group bit mask: 0070
  149. // - All bit mask: 0007
  150. //
  151. // For each, read is an octal value of `1`, write `2`, and execute `4`.
  152. //
  153. // Windows gracefully degrades to the effective permissions modeled using
  154. // these values.
  155. using ModeType = mode_t;
  156. // Enumeration of the different file types recognized.
  157. //
  158. // In addition to the specific type values being arranged for ease of use with
  159. // the POSIX APIs, the underlying type of the enum is arranged to use the common
  160. // mode type.
  161. enum class FileType : ModeType {
  162. // Portable file types that need to be supported across platform
  163. // implementations.
  164. Directory = S_IFDIR,
  165. RegularFile = S_IFREG,
  166. SymbolicLink = S_IFLNK,
  167. // Non-portable Unix-like platform specific types.
  168. UnixFifo = S_IFIFO,
  169. UnixCharDevice = S_IFCHR,
  170. UnixBlockDevice = S_IFBLK,
  171. UnixSocket = S_IFSOCK,
  172. // Mask for the Unix-like types to allow easy extraction.
  173. UnixMask = S_IFMT,
  174. };
  175. using Clock = std::chrono::file_clock;
  176. using Duration = std::chrono::duration<__int128, std::nano>;
  177. using TimePoint = std::chrono::time_point<Clock, Duration>;
  178. // Enumerates the different open access modes available.
  179. //
  180. // These are largely used to parameterize types in order to constrain which API
  181. // subset is available, and rarely needed directly.
  182. enum class OpenAccess {
  183. ReadOnly = O_RDONLY,
  184. WriteOnly = O_WRONLY,
  185. ReadWrite = O_RDWR,
  186. };
  187. // Forward declarations of various types that appear in APIs.
  188. class DirRef;
  189. class Dir;
  190. class RemovingDir;
  191. template <OpenAccess A>
  192. class FileRef;
  193. template <OpenAccess A>
  194. class File;
  195. class FdError;
  196. class PathError;
  197. namespace Internal {
  198. class FileRefBase;
  199. } // namespace Internal
  200. // Returns a constant `Dir` object that models the open current working
  201. // directory.
  202. //
  203. // Whatever the working directory of the process is will be used as the base for
  204. // any relative path operations on this object. For example, on Unix-like
  205. // systems, `Cwd().Stat("some/path")` is equivalent to `stat("some/path")`.
  206. consteval auto Cwd() -> Dir;
  207. // Creates a temporary directory and returns a removing directory handle to it.
  208. //
  209. // Each directory created will be unique and newly created by the call. It is
  210. // the caller's responsibility to clean up this directory.
  211. auto MakeTmpDir() -> ErrorOr<RemovingDir, Error>;
  212. // Creates a temporary directory and returns a removing directory handle to it.
  213. //
  214. // The path of the temporary directory will use the provided prefix, and will
  215. // not add any additional directory separators. Every component but the last in
  216. // the prefix path must exist and be a directory, the last directory must be
  217. // writable.
  218. auto MakeTmpDirWithPrefix(std::filesystem::path prefix)
  219. -> ErrorOr<RemovingDir, Error>;
  220. // Class modeling a file (or directory) status information structure.
  221. //
  222. // This provides a largely-portable model that callers can use, as well as a few
  223. // APIs to access non-portable implementation details when necessary.
  224. class FileStatus {
  225. public:
  226. // The size of the file in bytes.
  227. auto size() const -> int64_t { return stat_buf_.st_size; }
  228. auto type() const -> FileType {
  229. return static_cast<FileType>(stat_buf_.st_mode &
  230. static_cast<ModeType>(FileType::UnixMask));
  231. }
  232. // Convenience predicates to test for specific values of `type()`.
  233. auto is_dir() const -> bool { return type() == FileType::Directory; }
  234. auto is_file() const -> bool { return type() == FileType::RegularFile; }
  235. auto is_symlink() const -> bool { return type() == FileType::SymbolicLink; }
  236. // The read, write, and execute permissions for user, group, and others. See
  237. // the `ModeType` documentation for how to interpret the result.
  238. auto permissions() const -> ModeType { return stat_buf_.st_mode & 0777; }
  239. auto mtime() const -> TimePoint {
  240. // Linux, FreeBSD, and OpenBSD all use `st_mtim`, but macOS uses a different
  241. // spelling.
  242. #if __APPLE__
  243. timespec ts = stat_buf_.st_mtimespec;
  244. #else
  245. timespec ts = stat_buf_.st_mtim;
  246. #endif
  247. TimePoint t(std::chrono::seconds(ts.tv_sec));
  248. return t + std::chrono::nanoseconds(ts.tv_nsec);
  249. }
  250. // Non-portable APIs only available on Unix-like systems. See the
  251. // documentation of the Unix `stat` structure fields they expose for their
  252. // meaning.
  253. auto unix_inode() const -> uint64_t { return stat_buf_.st_ino; }
  254. auto unix_uid() const -> uid_t { return stat_buf_.st_uid; }
  255. private:
  256. friend DirRef;
  257. friend Internal::FileRefBase;
  258. FileStatus() = default;
  259. struct stat stat_buf_ = {};
  260. };
  261. // Models a held lock on a file or directory.
  262. //
  263. // Can model either a shared or exclusive lock with respect to the file, but the
  264. // held lock is unique.
  265. //
  266. // Must be released prior to the underlying file or directory being closed as it
  267. // contains a non-owning reference to that underlying file.
  268. class FileLock {
  269. public:
  270. enum class Kind {
  271. Shared = LOCK_SH,
  272. Exclusive = LOCK_EX,
  273. };
  274. using enum Kind;
  275. FileLock() = default;
  276. FileLock(FileLock&& arg) noexcept : fd_(std::exchange(arg.fd_, -1)) {}
  277. auto operator=(FileLock&& arg) noexcept -> FileLock& {
  278. Destroy();
  279. fd_ = std::exchange(arg.fd_, -1);
  280. return *this;
  281. }
  282. ~FileLock() { Destroy(); }
  283. // Returns true if the lock is currently held.
  284. auto is_locked() const -> bool { return fd_ != -1; }
  285. private:
  286. friend Internal::FileRefBase;
  287. explicit FileLock(int fd) : fd_(fd) {}
  288. auto Destroy() -> void;
  289. int fd_ = -1;
  290. };
  291. // The base class defining the core `File` API.
  292. //
  293. // While not used directly, this is the base class used to implement all of the
  294. // main `File` types: `ReadFileRef`, `WriteFileRef`, and `ReadWriteFileRef`.
  295. //
  296. // Objects using this type have access to an open file handle to a specific file
  297. // and expose operations on that open file. These operations may fail directly
  298. // with their `ErrorOr` return, but some errors may be deferred until the
  299. // underlying owning file is closed.
  300. //
  301. // The type provides reference semantics to the underlying file, but is
  302. // rebindable, movable, and copyable unlike a C++ language reference.
  303. class Internal::FileRefBase {
  304. public:
  305. // This object can be default constructed, but will hold an invalid file
  306. // handle in that case. This is to support rebinding operations.
  307. FileRefBase() = default;
  308. // Returns true if this refers to a valid open file, and false otherwise.
  309. auto is_valid() const -> bool { return fd_ != -1; }
  310. // Reads the file status.
  311. //
  312. // Analogous to the Unix-like `fstat` call.
  313. auto Stat() -> ErrorOr<FileStatus, FdError>;
  314. // Updates the access and modification times for the open file.
  315. //
  316. // If no explicit `time_point` is provided, sets both times to the current
  317. // time. If an explicit `time_point` is provided, the times are updated to
  318. // that time.
  319. auto UpdateTimes(std::optional<TimePoint> time_point = std::nullopt)
  320. -> ErrorOr<Success, FdError>;
  321. // Methods to seek the current file position, with various semantics for the
  322. // offset.
  323. auto Seek(int64_t delta) -> ErrorOr<int64_t, FdError>;
  324. auto SeekFromBeginning(int64_t delta_from_beginning)
  325. -> ErrorOr<int64_t, FdError>;
  326. auto SeekFromEnd(int64_t delta_from_end) -> ErrorOr<int64_t, FdError>;
  327. // Truncates or extends the size of the file to the provided size.
  328. //
  329. // If the new size is smaller, all bytes beyond this size will be unavailable.
  330. // If the new size is larger, the file will be zero-filled to the new size.
  331. // The position of reads and writes does not change.
  332. auto Truncate(int64_t new_size) -> ErrorOr<Success, FdError>;
  333. // Reads as much data as is available and fits into the provided buffer.
  334. //
  335. // On success, this returns a new slice from the start to the end of the
  336. // successfully read bytes. These will always be located in the passed-in
  337. // buffer, but not all of the buffer may be filled. A partial read does not
  338. // mean that the end of the file has been reached.
  339. //
  340. // When a successful read with an *empty* slice is returned, that represents
  341. // reaching EOF on the underlying file successfully and there is no more data
  342. // to read.
  343. //
  344. // This method retries `EINTR` on Unix-like systems and returns
  345. // other errors to the caller.
  346. auto ReadToBuffer(llvm::MutableArrayRef<std::byte> buffer)
  347. -> ErrorOr<llvm::MutableArrayRef<std::byte>, FdError>;
  348. // Writes as much data as possible from the provided buffer.
  349. //
  350. // On success, this returns a new slice of the *unwritten* bytes still present
  351. // in the buffer. An empty return represents a successful write of all bytes
  352. // in the buffer. A non-empty return does not represent an error or the
  353. // inability to finish writing.
  354. //
  355. // This method retries `EINTR` on Unix-like systems and returns
  356. // other errors to the caller.
  357. auto WriteFromBuffer(llvm::ArrayRef<std::byte> buffer)
  358. -> ErrorOr<llvm::ArrayRef<std::byte>, FdError>;
  359. // Returns an LLVM `raw_fd_ostream` that writes to this file.
  360. //
  361. // Note that this doesn't expose any write errors here, those will surface
  362. // through the `raw_fd_ostream` API. The stream will also not close the file
  363. // which remains owned by the owning `File` object.
  364. auto WriteStream() -> llvm::raw_fd_ostream;
  365. // Reads the file from its start until EOF into the returned string.
  366. //
  367. // This method will retry any recoverable errors and work to completely read
  368. // the file contents from its beginning up to first encountering EOF. This
  369. // will seek the file to ensure it starts at the beginning regardless of
  370. // previous read or write operations.
  371. //
  372. // Any non-recoverable errors are returned to the caller.
  373. auto ReadFileToString() -> ErrorOr<std::string, FdError>;
  374. // Writes the provided string to the file from the start and truncating to the
  375. // written size.
  376. //
  377. // This method will retry any recoverable errors and work to completely write
  378. // the provided content into the file from its beginning, and truncate the
  379. // file's size to the provided string size. Essentially, this function
  380. // replaces the file contents with the string's contents.
  381. //
  382. // Any non-recoverable errors are returned to the caller.
  383. auto WriteFileFromString(llvm::StringRef str) -> ErrorOr<Success, FdError>;
  384. // Attempt to acquire an advisory shared lock on this directory.
  385. //
  386. // This is always done as a non-blocking operation, as blocking on advisory
  387. // locks without a deadline can easily result in build systems essentially
  388. // "fork-bombing" a machine. However, a `deadline` duration can be provided
  389. // and this routine will block and attempt to acquire the requested lock for a
  390. // bounded amount of time approximately based on that duration. Further, a
  391. // `poll_interval` can be provided to control how quickly the lock will be
  392. // polled during that duration. There is no scaling of the poll intervals at
  393. // this layer, if a back-off heuristic is desired the caller should manage the
  394. // polling themselves. The goal is to allow simple cases of spurious failures
  395. // to be easily handled without unbounded blocking calls. Typically, callers
  396. // should use a duration that is a reasonable upper bound on the latency to
  397. // begin the locked operation and a poll interval that is a reasonably low
  398. // median latency to begin the operation as 1-2 polls is expected to be
  399. // common. These should not be set anywhere near the cost of acquiring a file
  400. // lock, and in general file locks should only be used for expensive
  401. // operations where it is worth significant delays to avoid duplicate work.
  402. //
  403. // If the lock cannot be acquired, the most recent lock-attempt error is
  404. // returned.
  405. auto TryLock(FileLock::Kind kind, Duration deadline = {},
  406. Duration poll_interval = {}) -> ErrorOr<FileLock, FdError>;
  407. protected:
  408. explicit FileRefBase(int fd) : fd_(fd) {}
  409. // Note: this should only be used or made part of the public API by subclasses
  410. // that provide *ownership* of the open file. It is implemented here to
  411. // provide a single, non-templated implementation.
  412. auto Close() && -> ErrorOr<Success, FdError>;
  413. // Factored out code to destroy an open read-only file. This calls `Close`
  414. // above but ignores any errors as there is no risk of data loss for a
  415. // read-only file.
  416. //
  417. // Note: this is a private API that should not be made public, and should only
  418. // be used by the implementation of subclass destructors. It should also only
  419. // be called for subclasses with *ownership* of the file reference, and is
  420. // provided here as a single non-template implementation.
  421. auto ReadOnlyDestroy() -> void;
  422. // Factored out code to destroy an open writable file. This _requires_ the
  423. // file to have already been closed with an explicit `Close` call, where it
  424. // can report any errors. Without that, destroying a writable file can easily
  425. // result in unnoticed data loss.
  426. //
  427. // Note: this is a private API that should not be made public, and should only
  428. // be used by the implementation of subclass destructors. It should also only
  429. // be called for subclasses with *ownership* of the file reference, and is
  430. // provided here as a single non-template implementation.
  431. auto WriteableDestroy() -> void;
  432. // State representing a potentially open file.
  433. //
  434. // On POSIX systems, this will be a file descriptor. For moved-from and
  435. // default-constructed file objects this may be an invalid negative value to
  436. // signal that state.
  437. //
  438. // TODO: This should be customized on non-POSIX systems.
  439. //
  440. // This member is made protected rather than private as the derived classes
  441. // need direct access to it in several contexts.
  442. // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
  443. int fd_ = -1;
  444. };
  445. // A non-owning reference to an open file.
  446. //
  447. // Instances model a reference to an open file. Generally, rather than using a
  448. // `WriteFile&`, code should use a `WriteFileRef`.
  449. //
  450. // A specific instance provides the subset of the file API suitable for its
  451. // access based on its template parameter: read, write, or both.
  452. //
  453. // The API for file references is factored into a base class
  454. // `Internal::FileRefBase` to avoid duplication for each access instantiation.
  455. // Only the methods that are constrained by access are defined here, and they
  456. // are defined as wrappers around methods in the base where the documentation
  457. // and implementation live.
  458. template <OpenAccess A>
  459. class FileRef : public Internal::FileRefBase {
  460. public:
  461. static constexpr bool Readable =
  462. A == OpenAccess::ReadOnly || A == OpenAccess::ReadWrite;
  463. static constexpr bool Writeable =
  464. A == OpenAccess::WriteOnly || A == OpenAccess::ReadWrite;
  465. // This object can be default constructed, but will hold an invalid file
  466. // handle in that case. This is to support rebinding operations.
  467. FileRef() = default;
  468. // Read and Write methods that delegate to the `FileRefBase` implementations,
  469. // but require the relevant access. See the methods on `FileRefBase` for full
  470. // documentation.
  471. auto Truncate(int64_t new_size) -> ErrorOr<Success, FdError>
  472. requires Writeable;
  473. auto ReadToBuffer(llvm::MutableArrayRef<std::byte> buffer)
  474. -> ErrorOr<llvm::MutableArrayRef<std::byte>, FdError>
  475. requires Readable;
  476. auto WriteFromBuffer(llvm::ArrayRef<std::byte> buffer)
  477. -> ErrorOr<llvm::ArrayRef<std::byte>, FdError>
  478. requires Writeable;
  479. auto WriteStream() -> llvm::raw_fd_ostream
  480. requires Writeable;
  481. auto ReadFileToString() -> ErrorOr<std::string, FdError>
  482. requires Readable;
  483. auto WriteFileFromString(llvm::StringRef str) -> ErrorOr<Success, FdError>
  484. requires Writeable;
  485. protected:
  486. friend File<A>;
  487. friend DirRef;
  488. // Other constructors from the base are also available, but remain protected.
  489. using FileRefBase::FileRefBase;
  490. };
  491. // Convenience type defs for the three access combinations.
  492. using ReadFileRef = FileRef<OpenAccess::ReadOnly>;
  493. using WriteFileRef = FileRef<OpenAccess::WriteOnly>;
  494. using ReadWriteFileRef = FileRef<OpenAccess::ReadWrite>;
  495. // An owning handle to an open file.
  496. //
  497. // This extends the `FileRef` API to provide ownership of the file handle. Most
  498. // of the API is defined by `FileRef`.
  499. //
  500. // The file will be closed when the object is destroyed, and must close without
  501. // errors. If there is a chance of errors on close, and that is often where
  502. // errors are reported, code must use the `Close` API to directly handle them or
  503. // it must be correct to check-fail on them.
  504. //
  505. // This type allows intentional "slicing" to the `FileRef` base class as that is
  506. // a correct and safe conversion to pass a non-owning reference to a file to
  507. // another function, much like binding a reference to an owning type is
  508. // implicit.
  509. template <OpenAccess A>
  510. class File : public FileRef<A> {
  511. public:
  512. static constexpr bool Readable =
  513. A == OpenAccess::ReadOnly || A == OpenAccess::ReadWrite;
  514. static constexpr bool Writeable =
  515. A == OpenAccess::WriteOnly || A == OpenAccess::ReadWrite;
  516. // Default constructs an invalid file.
  517. //
  518. // This can be destroyed or assigned safely, but no other operations are
  519. // correct.
  520. File() = default;
  521. // File objects are move-only as they model ownership.
  522. File(File&& arg) noexcept : FileRef<A>(std::exchange(arg.fd_, -1)) {}
  523. auto operator=(File&& arg) noexcept -> File& {
  524. Destroy();
  525. this->fd_ = std::exchange(arg.fd_, -1);
  526. return *this;
  527. }
  528. File(const File&) = delete;
  529. auto operator=(const File&) -> File& = delete;
  530. ~File() { Destroy(); }
  531. // Closes the open file and leaves the file in a moved-from state.
  532. //
  533. // The signature is `auto Close() && -> ErrorOr<Success, FdError>`.
  534. //
  535. // This type provides ownership of the file, so expose the `Close` method to
  536. // allow checked destruction and release of the file resources.
  537. //
  538. // If any errors are encountered during closing, returns them. Note that the
  539. // file should still be considered closed, and the object is moved-from even
  540. // if errors occur.
  541. using Internal::FileRefBase::Close;
  542. private:
  543. friend DirRef;
  544. // Destroy the file.
  545. //
  546. // This dispatches to non-template code in `FileRefBase` based on whether the
  547. // file is writable or readonly. The core logic is in the non-template
  548. // methods.
  549. auto Destroy() -> void;
  550. explicit File(int fd) : FileRef<A>(fd) {}
  551. };
  552. // Convenience type defs for the three access combinations.
  553. using ReadFile = File<OpenAccess::ReadOnly>;
  554. using WriteFile = File<OpenAccess::WriteOnly>;
  555. using ReadWriteFile = File<OpenAccess::ReadWrite>;
  556. // A non-owning reference to an open directory.
  557. //
  558. // This is the main API for accessing and opening files and other directories.
  559. // Conceptually, every open file or directory is relative to some other
  560. // directory. The symbolic current working directory object is available via the
  561. // `Cwd()` function. When on a Unix-like platform, this is intended to provide
  562. // the semantics of `openat` and related functions, including the ability to
  563. // write secure filesystem operations in the face of adversarial parallel
  564. // filesystem operations.
  565. //
  566. // Relative path parameters are always relative to this directory. Absolute path
  567. // parameters are also allowed and are treated as absolute paths. This parallels
  568. // the behavior of `/` for path concatenation where an absolute path ignores all
  569. // preceding components.
  570. //
  571. // Errors for directory operations retain the path parameter used in order to
  572. // print helpful detail when unhandled, but otherwise work to be lazy and
  573. // lightweight to support low-overhead expected error patterns.
  574. //
  575. // The names are designed to mirror the underlying Unix-like APIs that implement
  576. // them, with extensions to add clarity. However, the set of operations is
  577. // expected to be reasonable to implement on Windows with reasonable fidelity.
  578. class DirRef {
  579. public:
  580. class Entry;
  581. class Iterator;
  582. class Reader;
  583. constexpr DirRef() = default;
  584. // Returns true if this refers to a valid open directory, and false otherwise.
  585. auto is_valid() const -> bool { return dfd_ != -1; }
  586. // Begin reading the entries in a directory.
  587. //
  588. // This returns a `Reader` object that can be iterated to walk over all the
  589. // entries in this directory. Note that the returned `Reader` owns a newly
  590. // allocated handle to this directory, and provides the full `DirRef` API. If
  591. // it isn't necessary to keep both open, the `Dir` class offers a
  592. // move-qualified method `TakeAndRead` that optimizes this case.
  593. //
  594. // Note that it is unspecified whether added and removed files during the
  595. // lifetime of the reader will be included when iterating, but otherwise
  596. // concurrent mutations are well defined.
  597. auto Read() -> ErrorOr<Reader, FdError>;
  598. // Reads all of the entries in this directory into a vector.
  599. //
  600. // A helper function wrapping `Read` and walking the resulting reader's
  601. // entries to produce a container.
  602. //
  603. // For details on errors, see the documentation of `Read` and `Reader`.
  604. auto ReadEntries()
  605. -> ErrorOr<llvm::SmallVector<std::filesystem::path>, FdError>;
  606. // Reads the directory and appends entries to a container if they pass a
  607. // predicate. The predicate can be null, which is treated as if it always
  608. // returns true.
  609. //
  610. // For details on errors, see the documentation of `Read` and `Reader`.
  611. auto AppendEntriesIf(
  612. llvm::SmallVectorImpl<std::filesystem::path>& entries,
  613. llvm::function_ref<auto(llvm::StringRef name)->bool> predicate = {})
  614. -> ErrorOr<Success, FdError>;
  615. // Reads the directory and appends entries to one of two containers if they
  616. // pass a predicate. The predicate can be null, which is treated as if it
  617. // always returns true.
  618. //
  619. // Which container an entry is appended to depends on its kind -- directories
  620. // go to the first and non-directories go to the second. This turns out to be
  621. // a very common split with subdirectories often needing separate handling
  622. // from other entries.
  623. //
  624. // For details on errors, see the documentation of `Read` and `Reader`. This
  625. // may also `Stat` entries if necessary to determine whether they are
  626. // directories.
  627. auto AppendEntriesIf(
  628. llvm::SmallVectorImpl<std::filesystem::path>& dir_entries,
  629. llvm::SmallVectorImpl<std::filesystem::path>& non_dir_entries,
  630. llvm::function_ref<auto(llvm::StringRef name)->bool> predicate = {})
  631. -> ErrorOr<Success, FdError>;
  632. // Checks that the provided path can be accessed.
  633. auto Access(const std::filesystem::path& path,
  634. AccessCheckFlags check = AccessCheckFlags::Exists)
  635. -> ErrorOr<bool, PathError>;
  636. // Reads the `FileStatus` for the open directory.
  637. auto Stat() -> ErrorOr<FileStatus, FdError>;
  638. // Reads the `FileStatus` for the provided path (without opening it).
  639. //
  640. // Like the `stat` system call on Unix-like platforms, this will follow any
  641. // symlinks and provide the status of the underlying file or directory.
  642. auto Stat(const std::filesystem::path& path)
  643. -> ErrorOr<FileStatus, PathError>;
  644. // Reads the `FileStatus` for the provided path (without opening it).
  645. //
  646. // Like the `lstat` system call on Unix-like platforms, this will *not* follow
  647. // symlinks, and instead will return the status of the symlink itself.
  648. auto Lstat(const std::filesystem::path& path)
  649. -> ErrorOr<FileStatus, PathError>;
  650. // Updates the access and modification times for the provided path.
  651. //
  652. // If no explicit `time_point` is provided, sets both times to the current
  653. // time. If an explicit `time_point` is provided, the times are updated to
  654. // that time.
  655. auto UpdateTimes(const std::filesystem::path& path,
  656. std::optional<TimePoint> time_point = std::nullopt)
  657. -> ErrorOr<Success, PathError>;
  658. // Reads the target string of the symlink at the provided path.
  659. //
  660. // This does not follow the symlink, and does not require the symlink target
  661. // to be valid or exist. It merely reads the textual string.
  662. //
  663. // Returns an error if called with a path that is not a symlink.
  664. auto Readlink(const std::filesystem::path& path)
  665. -> ErrorOr<std::string, PathError>;
  666. // Opens the provided path as a read-only file.
  667. //
  668. // The interaction with an existing file is governed by `creation_options` and
  669. // defaults to error unless opening an existing file. When creating a file,
  670. // only the leaf component in the provided path can be created with this call.
  671. //
  672. // If creating a file, the file is created with `creation_mode` which defaults
  673. // to a restrictive `0600`. The creation permission bits are also completely
  674. // independent of the access provided via the opened file. For example,
  675. // creating with write permissions doesn't impact whether write access is
  676. // available via the returned file. And creating _without_ write permission
  677. // bits is compatible with opening the file for writing.
  678. //
  679. // Additional flags can be provided to `flags` to control other aspects of
  680. // behavior on open.
  681. //
  682. // This is an error if the path exists and is a directory. If the path is a
  683. // symlink, it will follow the symlink.
  684. auto OpenReadOnly(const std::filesystem::path& path,
  685. CreationOptions creation_options = OpenExisting,
  686. ModeType creation_mode = 0600,
  687. OpenFlags flags = OpenFlags::None)
  688. -> ErrorOr<ReadFile, PathError>;
  689. // Opens the provided path as a write-only file. Otherwise, behaves as
  690. // `OpenReadOnly`.
  691. auto OpenWriteOnly(const std::filesystem::path& path,
  692. CreationOptions creation_options = OpenExisting,
  693. ModeType creation_mode = 0600,
  694. OpenFlags flags = OpenFlags::None)
  695. -> ErrorOr<WriteFile, PathError>;
  696. // Opens the provided path as a read-and-write file. Otherwise, behaves as
  697. // `OpenReadOnly`.
  698. auto OpenReadWrite(const std::filesystem::path& path,
  699. CreationOptions creation_options = OpenExisting,
  700. ModeType creation_mode = 0600,
  701. OpenFlags flags = OpenFlags::None)
  702. -> ErrorOr<ReadWriteFile, PathError>;
  703. // Opens the provided path as a directory.
  704. //
  705. // Similar to `OpenReadOnly` and other file opening APIs, accepts
  706. // `creation_options` to control the interaction with any existing directory.
  707. // However, `CreateAlways` is not implementable for directories and an error
  708. // if passed. The default permissions in the `creation_mode` are `0700` which
  709. // is more suitable for directories. There are no extra flags that can be
  710. // passed.
  711. //
  712. // As with other open routines, when creating a directory, only the leaf
  713. // component can be created by the call to this routine.
  714. //
  715. // When creating a directory with `CreateNew`, this routine works to be safe
  716. // even in the presence of adversarial, concurrent operations that attempt to
  717. // replace the created directory with one that is controlled by the adversary.
  718. //
  719. // Specifically, for `CreateNew` we ensure that the last component is a
  720. // created directory in its parent, and cannot be replaced by a symlink into
  721. // an attacker-controlled directory. We further ensure it cannot have been
  722. // replaced by a directory with a different owner or with wider permissions
  723. // than the created directory.
  724. //
  725. // However, no validation is done on any prefix path components leading to the
  726. // leaf component created. When securely creating directories, the initial
  727. // creation should have a single component from an opened existing parent
  728. // directory. Also, no validation of the owning _group_ is performed. When
  729. // securely creating a directory, the caller should either ensure the parent
  730. // directory does not have a malicious setgid bit set, or restrict the
  731. // created mode to not give group access, or both. In general, the lack of
  732. // control over the owning group motivates our choice to make the default mode
  733. // permissions restrictive and not include any group access.
  734. //
  735. // To securely achieve a result similar to `OpenAlways` instead of
  736. // `CreateNew`, callers can directly `CreateNew` and handle failures with an
  737. // explicit `OpenExisting` that also blocks following symlinks with
  738. // `OpenFlags::NoFollow` and performs any needed validation.
  739. auto OpenDir(const std::filesystem::path& path,
  740. CreationOptions creation_options = OpenExisting,
  741. ModeType creation_mode = 0700, OpenFlags flags = OpenFlags::None)
  742. -> ErrorOr<Dir, PathError>;
  743. // Reads the file at the provided path to a string.
  744. //
  745. // This is a convenience wrapper for opening the path, reading the returned
  746. // file to a string, and closing it. Errors from any step are returned.
  747. auto ReadFileToString(const std::filesystem::path& path)
  748. -> ErrorOr<std::string, PathError>;
  749. // Writes the provided `content` to the provided path.
  750. //
  751. // This is a convenience wrapper for opening the path, creating it according
  752. // to `creation_options` as necessary, writing `content` to it, and closing
  753. // it. Errors from any step are returned.
  754. auto WriteFileFromString(const std::filesystem::path& path,
  755. llvm::StringRef content,
  756. CreationOptions creation_options = CreateAlways)
  757. -> ErrorOr<Success, PathError>;
  758. // Renames an entry from one directory to another directory, replacing any
  759. // existing entry with the target path.
  760. //
  761. // Note that this is *not* a general purpose move! It must be possible for
  762. // this operation to be performed as a metadata-only change, and so without
  763. // moving any actual data. This means it will not work across devices, mounts,
  764. // or filesystems. However, these restrictions make this an *atomic* rename.
  765. //
  766. // The most common usage is to rename an entry within a single directory, by
  767. // passing `*this` as `target_dir`.
  768. auto Rename(const std::filesystem::path& path, DirRef target_dir,
  769. const std::filesystem::path& target_path)
  770. -> ErrorOr<Success, PathError>;
  771. // Changes the current working directory to this directory.
  772. auto Chdir() -> ErrorOr<Success, FdError>;
  773. // Changes the current working directory to the provided path.
  774. //
  775. // An error if the provided path is not a directory. Does not open the
  776. // provided path as a directory, but it will be available as the current
  777. // working directory via `Cwd()`.
  778. auto Chdir(const std::filesystem::path& path) -> ErrorOr<Success, PathError>;
  779. // Creates a symlink at the provided path with the contents of `target`.
  780. //
  781. // Note that the target of a symlink is an arbitrary string and there is no
  782. // error checking on whether it exists or is sensible. Also, the target string
  783. // set will be up to the first null byte in `target`, regardless of its
  784. // `size`. This will not overwrite an existing symlink at the provided path.
  785. //
  786. // Also note that the written symlink will be the null-terminated string
  787. // `target.c_str()`, ignoring everything past any embedded null bytes.
  788. auto Symlink(const std::filesystem::path& path, const std::string& target)
  789. -> ErrorOr<Success, PathError>;
  790. // Creates the directories in the provided path, using the permissions in
  791. // `creation_mode`.
  792. //
  793. // This will create any missing directory components in `path`. Relative paths
  794. // will be created relative to this directory, and without re-resolving its
  795. // path. The leaf created directory is opened and returned.
  796. //
  797. // The implementation allows for concurrent creation of the same directory (or
  798. // a prefix) without error or corruption and optimizes for performance of
  799. // creating the requested path. As a consequence, this creation is _unsafe_ in
  800. // the face of adversarial concurrent manipulation of components of the path.
  801. // If you need to create directories securely, first create an initial
  802. // directory securely using `OpenDir` and `CreateNew` with restricted
  803. // permissions that preclude any adversarial behavior, then use this API to
  804. // create tree components within that root.
  805. auto CreateDirectories(const std::filesystem::path& path,
  806. ModeType creation_mode = 0700)
  807. -> ErrorOr<Dir, PathError>;
  808. // Unlink the last component of the path, removing that name from its parent
  809. // directory.
  810. //
  811. // If this was the last link to the underlying file its contents will be
  812. // removed when the last open file handle to it is closed.
  813. //
  814. // The path must not be a directory. If the path is a symbolic link, the link
  815. // will be removed, not the target. Models the behavior of `unlinkat(2)` on
  816. // Unix-like platforms.
  817. auto Unlink(const std::filesystem::path& path) -> ErrorOr<Success, PathError>;
  818. // Remove the directory entry of the last component of the path.
  819. //
  820. // The path must be a directory, and that directory must be empty. Models
  821. // `rmdirat(2)` on Unix-like platforms.
  822. auto Rmdir(const std::filesystem::path& path) -> ErrorOr<Success, PathError>;
  823. // Remove the directory tree identified by the last component of the path.
  824. //
  825. // The provided path must name a directory. This removes all files and
  826. // subdirectories contained within that named directory and then removes the
  827. // directory itself once empty.
  828. auto Rmtree(const std::filesystem::path& path) -> ErrorOr<Success, PathError>;
  829. protected:
  830. constexpr explicit DirRef(int dfd) : dfd_(dfd) {}
  831. // Slow-path fallback when unable to read the symlink target into a small
  832. // stack buffer.
  833. auto ReadlinkSlow(const std::filesystem::path& path)
  834. -> ErrorOr<std::string, PathError>;
  835. // Generic implementation of the various `Open*` variants using the
  836. // `OpenAccess` enumerator.
  837. template <OpenAccess A>
  838. auto OpenImpl(const std::filesystem::path& path,
  839. CreationOptions creation_options, ModeType creation_mode,
  840. OpenFlags flags) -> ErrorOr<File<A>, PathError>;
  841. // State representing an open directory.
  842. //
  843. // On POSIX systems, this will be a file descriptor. For moved-from and
  844. // default-constructed file objects this may be an invalid negative value to
  845. // signal that state.
  846. //
  847. // TODO: This should be customized on non-POSIX systems.
  848. //
  849. // The directory's file descriptor is part of the protected API.
  850. // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes):
  851. int dfd_ = -1;
  852. };
  853. // An owning handle to an open directory.
  854. //
  855. // This extends the `DirRef` API to provide ownership of the directory. Most of
  856. // the API is defined by `DirRef`. It additionally provides optimized move-based
  857. // variations on those APIs where relevant.
  858. //
  859. // The directory will be closed when the object is destroyed. Closing an open
  860. // directory isn't an interesting error reporting path and so no direct close
  861. // API is provided.
  862. //
  863. // This type allows intentional "slicing" to the `DirRef` base class as that is
  864. // a correct and safe conversion to pass a non-owning reference to a directory
  865. // to another function, much like binding a reference to an owning type is
  866. // implicit.
  867. class Dir : public DirRef {
  868. public:
  869. Dir() = default;
  870. // Dir objects are move-only as they model ownership.
  871. Dir(Dir&& arg) noexcept : DirRef(std::exchange(arg.dfd_, -1)) {}
  872. auto operator=(Dir&& arg) noexcept -> Dir& {
  873. Destroy();
  874. dfd_ = std::exchange(arg.dfd_, -1);
  875. return *this;
  876. }
  877. Dir(const Dir&) = delete;
  878. auto operator=(const Dir&) -> Dir& = delete;
  879. constexpr ~Dir();
  880. // An optimized way to read the entries in a directory when moving from an
  881. // owning `Dir` object.
  882. //
  883. // This avoids creating a duplicate file handle for the returned `Reader`.
  884. // That `Reader` also supports the full `DirRef` API and so can often be used
  885. // without retaining the original `Dir`.
  886. //
  887. // For more details about reading, see the documentation on `DirRef::Read`.
  888. auto TakeAndRead() && -> ErrorOr<Reader, FdError>;
  889. // Also include `DirRef`'s read API.
  890. using DirRef::Read;
  891. private:
  892. friend consteval auto Cwd() -> Dir;
  893. friend DirRef;
  894. friend RemovingDir;
  895. explicit constexpr Dir(int dfd) : DirRef(dfd) {}
  896. // Prevent implicit creation of a `Dir` object from a `RemovingDir` which will
  897. // end up as a subclass below and represent harmful implicit slicing. Instead,
  898. // require friendship and an explicit construction on an _intended_ release of
  899. // the removing semantics.
  900. explicit Dir(RemovingDir&& arg) noexcept;
  901. constexpr auto Destroy() -> void;
  902. };
  903. // An owning handle to an open directory and its absolute path that will be
  904. // removed recursively when destroyed.
  905. //
  906. // This can be used to ensure removal of a directory, and also exposes the
  907. // absolute path of the directory.
  908. //
  909. // As removal may encounter errors, unless the desired behavior is a
  910. // check-failure, users should explicitly move and call `Remove` at the end of
  911. // lifetime and handle any resultant errors.
  912. class RemovingDir : public Dir {
  913. public:
  914. // Takes ownership of the open directory `d` and wraps it in a `RemovingDir`
  915. // that will remove it on destruction using `path`. Note that for a relative
  916. // `path`, the removal will re-resolve this relative to the current working
  917. // directory on removal.
  918. //
  919. // Note that there is no way for the implementation to validate what directory
  920. // `path` refers to, that is the responsibility of the caller.
  921. explicit RemovingDir(Dir d, std::filesystem::path path)
  922. : Dir(std::move(d)), path_(std::move(path)) {}
  923. RemovingDir() = default;
  924. RemovingDir(RemovingDir&& arg) = default;
  925. auto operator=(RemovingDir&& rhs) -> RemovingDir& = default;
  926. ~RemovingDir();
  927. auto path() const [[clang::lifetimebound]] -> const std::filesystem::path& {
  928. return path_;
  929. }
  930. // Releases the directory from being removed and returns just the underlying
  931. // owning handle.
  932. auto Release() && -> Dir { return std::move(*this); }
  933. // Removes the directory immediately and surfaces any errors encountered.
  934. auto Remove() && -> ErrorOr<Success, PathError>;
  935. private:
  936. friend Dir;
  937. std::filesystem::path path_;
  938. };
  939. // A named entry in a directory.
  940. //
  941. // This provides access to the scanned data when reading the entries of the
  942. // directory. It can only be produced by iterating over a `DirRef::Reader`.
  943. class DirRef::Entry {
  944. public:
  945. // The name of the entry.
  946. //
  947. // This is exposed as a null-terminated C-string as that is the most common
  948. // representation.
  949. auto name() const -> const char* { return dent_->d_name; }
  950. // Test if the entry has an unknown type. In this case, all other type
  951. // predicates will return false and the caller will have to directly `Lstat()`
  952. // the entry to determine its type.
  953. auto is_unknown_type() const -> bool { return dent_->d_type == DT_UNKNOWN; }
  954. // Predicates to test for known entry types.
  955. //
  956. // Note that we don't provide an enumerator here as we don't have any reliable
  957. // way to predict the set of possible values or narrow to that set. Different
  958. // platforms and even different versions of the same header may change the set
  959. // of types surfaced here.
  960. auto is_known_dir() const -> bool { return dent_->d_type == DT_DIR; }
  961. auto is_known_regular_file() const -> bool { return dent_->d_type == DT_REG; }
  962. auto is_known_symlink() const -> bool { return dent_->d_type == DT_LNK; }
  963. private:
  964. friend Dir::Reader;
  965. friend Dir::Iterator;
  966. Entry() = default;
  967. explicit Entry(dirent* dent) : dent_(dent) {}
  968. dirent* dent_ = nullptr;
  969. };
  970. // An iterator into a `DirRef::Reader`, used for walking the entries in a
  971. // directory.
  972. //
  973. // Most of the work of iterating a directory is done when constructing the
  974. // `Reader`, when constructing the beginning iterator, or when incrementing the
  975. // iterator.
  976. class DirRef::Iterator
  977. : public llvm::iterator_facade_base<Iterator, std::input_iterator_tag,
  978. const Entry> {
  979. public:
  980. // Default construct a general end iterator.
  981. Iterator() = default;
  982. auto operator==(const Iterator& rhs) const -> bool {
  983. CARBON_DCHECK(dirp_ == nullptr || rhs.dirp_ == nullptr ||
  984. dirp_ == rhs.dirp_);
  985. return entry_.dent_ == rhs.entry_.dent_;
  986. }
  987. auto operator*() const [[clang::lifetimebound]] -> const Entry& {
  988. return entry_;
  989. }
  990. auto operator++() -> Iterator&;
  991. private:
  992. friend Dir::Reader;
  993. // Construct a begin iterator for a specific directory stream.
  994. explicit Iterator(DIR* dirp) : dirp_(dirp) {
  995. // Increment immediately to populate the initial entry.
  996. ++*this;
  997. }
  998. DIR* dirp_ = nullptr;
  999. Entry entry_;
  1000. };
  1001. // A reader for a directory.
  1002. //
  1003. // This class owns a handle to a directory that is set up for reading the
  1004. // entries within the directory. Because it owns a handle to the directory, it
  1005. // also implements the full `DirRef` API for convenience.
  1006. //
  1007. // Beyond the `DirRef` API, this object can be iterated as a range to visit all
  1008. // the entries in the directory.
  1009. //
  1010. // Note that it is unspecified whether entries added or removed prior to being
  1011. // visited while iterating. Iterating also cannot be re-started once begun --
  1012. // this models an input iterable range, not even a forward iterable range.
  1013. //
  1014. // This type allows intentional "slicing" to the `DirRef` base class as that is
  1015. // a correct and safe conversion to pass a non-owning reference to a directory
  1016. // to another function, much like binding a reference to an owning type is
  1017. // implicit.
  1018. class DirRef::Reader : public DirRef {
  1019. public:
  1020. Reader() = default;
  1021. Reader(Reader&& arg) noexcept
  1022. // The directory file descriptor isn't owning, but clear it for clarity.
  1023. : DirRef(std::exchange(arg.dfd_, -1)),
  1024. dirp_(std::exchange(arg.dirp_, nullptr)) {}
  1025. Reader(const Reader&) = delete;
  1026. auto operator=(Reader&& arg) noexcept -> Reader& {
  1027. Destroy();
  1028. // The directory file descriptor isn't owning, but clear it for clarity.
  1029. dfd_ = std::exchange(arg.dfd_, -1);
  1030. dirp_ = std::exchange(arg.dirp_, nullptr);
  1031. return *this;
  1032. }
  1033. ~Reader() { Destroy(); }
  1034. // Compute the begin and end iterators for reading the entries of the
  1035. // directory.
  1036. auto begin() -> Iterator;
  1037. auto end() -> Iterator;
  1038. private:
  1039. friend DirRef;
  1040. friend Dir;
  1041. explicit Reader(DIR* dirp) : DirRef(dirfd(dirp)), dirp_(dirp) {}
  1042. auto Destroy() -> void;
  1043. DIR* dirp_ = nullptr;
  1044. };
  1045. namespace Internal {
  1046. // Base class for `errno` errors.
  1047. //
  1048. // This is where we extract common APIs and logic for querying the specific
  1049. // `errno`-based error.
  1050. template <typename ErrorT>
  1051. class ErrnoErrorBase : public ErrorBase<ErrorT> {
  1052. public:
  1053. // Accessors to test for specific kinds of errors that are portably available.
  1054. auto already_exists() const -> bool { return errnum_ == EEXIST; }
  1055. auto is_dir() const -> bool { return errnum_ == EISDIR; }
  1056. auto no_entity() const -> bool { return errnum_ == ENOENT; }
  1057. auto not_dir() const -> bool { return errnum_ == ENOTDIR; }
  1058. auto access_denied() const -> bool { return errnum_ == EACCES; }
  1059. auto would_block() const -> bool { return errnum_ == EWOULDBLOCK; }
  1060. // Specific to `Rmdir` and `Rename` operations that remove a directory name,
  1061. // two different error values can be used.
  1062. auto not_empty() const -> bool {
  1063. return errnum_ == ENOTEMPTY || errnum_ == EEXIST;
  1064. }
  1065. // Accessor for the `errno` based error number. This is not a portable API,
  1066. // code using it will need to be ported to use a different API on Windows.
  1067. // TODO: Add a Windows-specific API for its low-level error information.
  1068. auto unix_errnum() const -> int { return errnum_; }
  1069. protected:
  1070. // NOLINTNEXTLINE(bugprone-crtp-constructor-accessibility):
  1071. explicit ErrnoErrorBase(int errnum) : errnum_(errnum) {}
  1072. private:
  1073. int errnum_;
  1074. };
  1075. } // namespace Internal
  1076. // Error from a file-descriptor operation.
  1077. //
  1078. // This is the implementation of the file-descriptor-based error type. When
  1079. // operations on a file descriptor fail, they use this object to convey the
  1080. // error plus the descriptor in question.
  1081. //
  1082. // Specific context on the exact point or nature of the operation that failed
  1083. // can be included in the custom format string. The format string should include
  1084. // a placeholder for the file descriptor to be substituted into. The format
  1085. // string should describe the _operation_ that failed, once rendered it will
  1086. // have `failed: ` and a description of the `errno`-indicated failure appended.
  1087. //
  1088. // For example:
  1089. //
  1090. // `FdError(EPERM, "Read of file '{0}'", 42)`
  1091. //
  1092. // Will be rendered similarly to:
  1093. //
  1094. // "Read of file '42' failed: EPERM: ..."
  1095. class FdError : public Internal::ErrnoErrorBase<FdError> {
  1096. public:
  1097. FdError(FdError&&) noexcept = default;
  1098. auto operator=(FdError&&) noexcept -> FdError& = default;
  1099. // Prints this error to the provided string.
  1100. //
  1101. // Works to render the `errno` in a friendly way and includes the file
  1102. // descriptor for context.
  1103. auto Print(llvm::raw_ostream& out) const -> void;
  1104. private:
  1105. friend FileLock;
  1106. friend Internal::FileRefBase;
  1107. friend ReadFile;
  1108. friend WriteFile;
  1109. friend ReadWriteFile;
  1110. friend DirRef;
  1111. friend Dir;
  1112. explicit FdError(int errnum, llvm::StringLiteral format, int fd)
  1113. : ErrnoErrorBase(errnum), fd_(fd), format_(format) {}
  1114. int fd_;
  1115. llvm::StringLiteral format_;
  1116. };
  1117. // Error from a path-based operation.
  1118. //
  1119. // This is the implementation of the path-based error type. When operations on a
  1120. // path fail, they use this object to convey the error plus both the path and
  1121. // relevant directory FD leading to the failure.
  1122. //
  1123. // Specific context on the exact point or nature of the operation that failed
  1124. // can be included in the custom format string. The format string should include
  1125. // placeholders for the path and the directory file descriptor to be substituted
  1126. // into. The format string should describe the _operation_ that failed, once
  1127. // rendered it will have `failed: ` and a description of the `errno`-indicated
  1128. // failure appended.
  1129. //
  1130. // For example:
  1131. //
  1132. // `PathError(EPERM, "Open of '{0}' relative to '{1}'", "filename", 42)`
  1133. //
  1134. // Will be rendered similarly to:
  1135. //
  1136. // "Open of 'filename' relative to '42' failed: EPERM: ..."
  1137. class PathError : public Internal::ErrnoErrorBase<PathError> {
  1138. public:
  1139. PathError(PathError&&) noexcept = default;
  1140. auto operator=(PathError&&) noexcept -> PathError& = default;
  1141. // Prints this error to the provided string.
  1142. //
  1143. // Works to render the `errno` in a friendly way and includes the path and
  1144. // directory file descriptor for context.
  1145. auto Print(llvm::raw_ostream& out) const -> void;
  1146. private:
  1147. friend DirRef;
  1148. friend Dir;
  1149. explicit PathError(int errnum, llvm::StringLiteral format,
  1150. std::filesystem::path path, int dir_fd)
  1151. : ErrnoErrorBase(errnum),
  1152. dir_fd_(dir_fd),
  1153. path_(std::move(path)),
  1154. format_(format) {}
  1155. int dir_fd_;
  1156. std::filesystem::path path_;
  1157. llvm::StringLiteral format_;
  1158. };
  1159. // Implementation details only below.
  1160. namespace Internal {
  1161. inline auto DurationToTimespec(Duration d) -> timespec {
  1162. timespec ts = {};
  1163. ts.tv_sec = std::chrono::duration_cast<std::chrono::seconds>(d).count();
  1164. d -= std::chrono::seconds(ts.tv_sec);
  1165. ts.tv_nsec = std::chrono::duration_cast<std::chrono::nanoseconds>(d).count();
  1166. return ts;
  1167. }
  1168. } // namespace Internal
  1169. consteval auto Cwd() -> Dir { return Dir(AT_FDCWD); }
  1170. inline auto FileLock::Destroy() -> void {
  1171. if (fd_ == -1) {
  1172. // Nothing to unlock.
  1173. return;
  1174. }
  1175. // We always try to unlock in a non-blocking way as there should never be a
  1176. // reason to block here.
  1177. int result = flock(fd_, LOCK_UN | LOCK_NB);
  1178. // The only realistic error is `EBADF` that would represent a programming
  1179. // error the type system should prevent. We conservatively check-fail if an
  1180. // error occurs here.
  1181. CARBON_CHECK(result == 0, "{0}",
  1182. FdError(errno, "Unexpected error while _unlocking_ '{0}'", fd_));
  1183. }
  1184. inline auto Internal::FileRefBase::Stat() -> ErrorOr<FileStatus, FdError> {
  1185. FileStatus status;
  1186. if (fstat(fd_, &status.stat_buf_) == 0) {
  1187. return status;
  1188. }
  1189. return FdError(errno, "File::Stat on '{0}'", fd_);
  1190. }
  1191. inline auto Internal::FileRefBase::UpdateTimes(
  1192. std::optional<TimePoint> time_point) -> ErrorOr<Success, FdError> {
  1193. if (!time_point) {
  1194. if (futimens(fd_, nullptr) == -1) {
  1195. return FdError(errno, "File::UpdateTimes to now on '{0}'", fd_);
  1196. }
  1197. return Success();
  1198. }
  1199. timespec times[2];
  1200. times[0] = Internal::DurationToTimespec(time_point->time_since_epoch());
  1201. times[1] = times[0];
  1202. if (futimens(fd_, times) == -1) {
  1203. return FdError(errno, "File::UpdateTimes to a specific time on '{0}'", fd_);
  1204. }
  1205. return Success();
  1206. }
  1207. inline auto Internal::FileRefBase::Seek(int64_t delta)
  1208. -> ErrorOr<int64_t, FdError> {
  1209. int64_t byte_offset = lseek(fd_, delta, SEEK_CUR);
  1210. if (byte_offset == -1) {
  1211. return FdError(errno, "File::Seek on '{0}'", fd_);
  1212. }
  1213. return byte_offset;
  1214. }
  1215. inline auto Internal::FileRefBase::SeekFromBeginning(
  1216. int64_t delta_from_beginning) -> ErrorOr<int64_t, FdError> {
  1217. int64_t byte_offset = lseek(fd_, delta_from_beginning, SEEK_SET);
  1218. if (byte_offset == -1) {
  1219. return FdError(errno, "File::SeekTo on '{0}'", fd_);
  1220. }
  1221. return byte_offset;
  1222. }
  1223. inline auto Internal::FileRefBase::SeekFromEnd(int64_t delta_from_end)
  1224. -> ErrorOr<int64_t, FdError> {
  1225. int64_t byte_offset = lseek(fd_, delta_from_end, SEEK_END);
  1226. if (byte_offset == -1) {
  1227. return FdError(errno, "File::SeekFromEnd on '{0}'", fd_);
  1228. }
  1229. return byte_offset;
  1230. }
  1231. inline auto Internal::FileRefBase::Truncate(int64_t new_size)
  1232. -> ErrorOr<Success, FdError> {
  1233. int64_t result = ftruncate(fd_, new_size);
  1234. if (result == -1) {
  1235. return FdError(errno, "File::Truncate on '{0}'", fd_);
  1236. }
  1237. return Success();
  1238. }
  1239. inline auto Internal::FileRefBase::ReadToBuffer(
  1240. llvm::MutableArrayRef<std::byte> buffer)
  1241. -> ErrorOr<llvm::MutableArrayRef<std::byte>, FdError> {
  1242. for (;;) {
  1243. ssize_t read_bytes = read(fd_, buffer.data(), buffer.size());
  1244. if (read_bytes == -1) {
  1245. if (errno == EINTR) {
  1246. continue;
  1247. }
  1248. return FdError(errno, "File::Read on '{0}'", fd_);
  1249. }
  1250. return buffer.slice(0, read_bytes);
  1251. }
  1252. }
  1253. inline auto Internal::FileRefBase::WriteFromBuffer(
  1254. llvm::ArrayRef<std::byte> buffer)
  1255. -> ErrorOr<llvm::ArrayRef<std::byte>, FdError> {
  1256. for (;;) {
  1257. ssize_t written_bytes = write(fd_, buffer.data(), buffer.size());
  1258. if (written_bytes == -1) {
  1259. if (errno == EINTR) {
  1260. continue;
  1261. }
  1262. return FdError(errno, "File::Write on '{0}'", fd_);
  1263. }
  1264. return buffer.drop_front(written_bytes);
  1265. }
  1266. }
  1267. inline auto Internal::FileRefBase::WriteStream() -> llvm::raw_fd_ostream {
  1268. return llvm::raw_fd_ostream(fd_, /*shouldClose=*/false);
  1269. }
  1270. inline auto Internal::FileRefBase::Close() && -> ErrorOr<Success, FdError> {
  1271. // Put the file in a moved-from state immediately as it is invalid to
  1272. // retry closing or use the file in any way even if the close fails.
  1273. int fd = std::exchange(fd_, -1);
  1274. int result = close(fd);
  1275. if (result == 0) {
  1276. return Success();
  1277. }
  1278. return FdError(errno, "File::Close on '{0}'", fd);
  1279. }
  1280. inline auto Internal::FileRefBase::ReadOnlyDestroy() -> void {
  1281. if (fd_ >= 0) {
  1282. auto result = std::move(*this).Close();
  1283. // Intentionally drop errors, as there is no interesting error here. There
  1284. // is no risk of data loss, and the least bad thing we can do is to just
  1285. // leak the file descriptor.
  1286. static_cast<void>(result);
  1287. }
  1288. }
  1289. inline auto Internal::FileRefBase::WriteableDestroy() -> void {
  1290. CARBON_CHECK(
  1291. fd_ == -1,
  1292. "Cannot destroy an open writable file, they _must_ be destroyed by "
  1293. "calling `Close` and handling any errors to avoid data loss.");
  1294. }
  1295. template <OpenAccess A>
  1296. auto FileRef<A>::Truncate(int64_t new_size) -> ErrorOr<Success, FdError>
  1297. requires Writeable
  1298. {
  1299. return FileRefBase::Truncate(new_size);
  1300. }
  1301. template <OpenAccess A>
  1302. auto FileRef<A>::ReadToBuffer(llvm::MutableArrayRef<std::byte> buffer)
  1303. -> ErrorOr<llvm::MutableArrayRef<std::byte>, FdError>
  1304. requires Readable
  1305. {
  1306. return FileRefBase::ReadToBuffer(buffer);
  1307. }
  1308. template <OpenAccess A>
  1309. auto FileRef<A>::ReadFileToString() -> ErrorOr<std::string, FdError>
  1310. requires Readable
  1311. {
  1312. return FileRefBase::ReadFileToString();
  1313. }
  1314. template <OpenAccess A>
  1315. auto FileRef<A>::WriteFromBuffer(llvm::ArrayRef<std::byte> buffer)
  1316. -> ErrorOr<llvm::ArrayRef<std::byte>, FdError>
  1317. requires Writeable
  1318. {
  1319. return FileRefBase::WriteFromBuffer(buffer);
  1320. }
  1321. template <OpenAccess A>
  1322. auto FileRef<A>::WriteStream() -> llvm::raw_fd_ostream
  1323. requires Writeable
  1324. {
  1325. return FileRefBase::WriteStream();
  1326. }
  1327. template <OpenAccess A>
  1328. auto FileRef<A>::WriteFileFromString(llvm::StringRef str)
  1329. -> ErrorOr<Success, FdError>
  1330. requires Writeable
  1331. {
  1332. return FileRefBase::WriteFileFromString(str);
  1333. }
  1334. template <OpenAccess A>
  1335. auto File<A>::Destroy() -> void {
  1336. if constexpr (Writeable) {
  1337. this->WriteableDestroy();
  1338. } else {
  1339. this->ReadOnlyDestroy();
  1340. }
  1341. }
  1342. inline auto DirRef::Read() -> ErrorOr<Reader, FdError> {
  1343. int dup_dfd = dup(dfd_);
  1344. if (dup_dfd == -1) {
  1345. // There are very few plausible errors here, but we can return one so it
  1346. // doesn't hurt to do so. While `EINTR` and `EBUSY` are mentioned in some
  1347. // documentation, there is no indication that for just `dup` it is useful to
  1348. // loop and retry.
  1349. return FdError(errno, "Dir::Read on '{0}'", dfd_);
  1350. }
  1351. return Dir(dup_dfd).TakeAndRead();
  1352. }
  1353. inline auto DirRef::ReadEntries()
  1354. -> ErrorOr<llvm::SmallVector<std::filesystem::path>, FdError> {
  1355. llvm::SmallVector<std::filesystem::path> entries;
  1356. CARBON_RETURN_IF_ERROR(AppendEntriesIf(entries));
  1357. return entries;
  1358. }
  1359. inline auto DirRef::Access(const std::filesystem::path& path,
  1360. AccessCheckFlags check) -> ErrorOr<bool, PathError> {
  1361. if (faccessat(dfd_, path.c_str(), static_cast<int>(check), /*flags=*/0) ==
  1362. 0) {
  1363. return true;
  1364. }
  1365. return PathError(errno, "Dir::Access on '{0}' relative to '{1}'", path, dfd_);
  1366. }
  1367. inline auto DirRef::Stat() -> ErrorOr<FileStatus, FdError> {
  1368. FileStatus status;
  1369. if (fstat(dfd_, &status.stat_buf_) == 0) {
  1370. return status;
  1371. }
  1372. return FdError(errno, "Dir::Stat on '{0}': ", dfd_);
  1373. }
  1374. inline auto DirRef::Stat(const std::filesystem::path& path)
  1375. -> ErrorOr<FileStatus, PathError> {
  1376. FileStatus status;
  1377. if (fstatat(dfd_, path.c_str(), &status.stat_buf_, /*flags=*/0) == 0) {
  1378. return status;
  1379. }
  1380. return PathError(errno, "Dir::Stat on '{0}' relative to '{1}'", path, dfd_);
  1381. }
  1382. inline auto DirRef::Lstat(const std::filesystem::path& path)
  1383. -> ErrorOr<FileStatus, PathError> {
  1384. FileStatus status;
  1385. if (fstatat(dfd_, path.c_str(), &status.stat_buf_,
  1386. /*flags=*/AT_SYMLINK_NOFOLLOW) == 0) {
  1387. return status;
  1388. }
  1389. return PathError(errno, "Dir::Lstat on '{0}' relative to '{1}'", path, dfd_);
  1390. }
  1391. inline auto DirRef::UpdateTimes(const std::filesystem::path& path,
  1392. std::optional<TimePoint> time_point)
  1393. -> ErrorOr<Success, PathError> {
  1394. if (!time_point) {
  1395. if (utimensat(dfd_, path.c_str(), nullptr, /*flags*/ 0) == -1) {
  1396. return PathError(errno,
  1397. "Dir::UpdateTimes to now on '{0}' relative to '{1}'",
  1398. path, dfd_);
  1399. }
  1400. return Success();
  1401. }
  1402. timespec times[2];
  1403. times[0] = Internal::DurationToTimespec(time_point->time_since_epoch());
  1404. times[1] = times[0];
  1405. if (utimensat(dfd_, path.c_str(), times, /*flags*/ 0) == -1) {
  1406. return PathError(
  1407. errno, "Dir::UpdateTimes to a specific time on '{0}' relative to '{1}'",
  1408. path, dfd_);
  1409. }
  1410. return Success();
  1411. }
  1412. inline auto DirRef::Readlink(const std::filesystem::path& path)
  1413. -> ErrorOr<std::string, PathError> {
  1414. // On the fast path, we read into a small stack buffer and get the whole
  1415. // contents.
  1416. constexpr ssize_t BufferSize = 256;
  1417. char buffer[BufferSize];
  1418. ssize_t read_bytes = readlinkat(dfd_, path.c_str(), buffer, BufferSize);
  1419. if (read_bytes == -1) {
  1420. return PathError(errno, "Dir::Readlink on '{0}' relative to '{1}'", path,
  1421. dfd_);
  1422. }
  1423. if (read_bytes < BufferSize) {
  1424. // We got the whole contents in one shot, return it.
  1425. return std::string(buffer, read_bytes);
  1426. }
  1427. // Otherwise, fallback to an out-of-line function to handle the slow path.
  1428. return ReadlinkSlow(path);
  1429. }
  1430. inline auto DirRef::OpenReadOnly(const std::filesystem::path& path,
  1431. CreationOptions creation_options,
  1432. ModeType creation_mode, OpenFlags flags)
  1433. -> ErrorOr<ReadFile, PathError> {
  1434. return OpenImpl<OpenAccess::ReadOnly>(path, creation_options, creation_mode,
  1435. flags);
  1436. }
  1437. inline auto DirRef::OpenWriteOnly(const std::filesystem::path& path,
  1438. CreationOptions creation_options,
  1439. ModeType creation_mode, OpenFlags flags)
  1440. -> ErrorOr<WriteFile, PathError> {
  1441. return OpenImpl<OpenAccess::WriteOnly>(path, creation_options, creation_mode,
  1442. flags);
  1443. }
  1444. inline auto DirRef::OpenReadWrite(const std::filesystem::path& path,
  1445. CreationOptions creation_options,
  1446. ModeType creation_mode, OpenFlags flags)
  1447. -> ErrorOr<ReadWriteFile, PathError> {
  1448. return OpenImpl<OpenAccess::ReadWrite>(path, creation_options, creation_mode,
  1449. flags);
  1450. }
  1451. inline auto DirRef::Rename(const std::filesystem::path& path, DirRef target_dir,
  1452. const std::filesystem::path& target_path)
  1453. -> ErrorOr<Success, PathError> {
  1454. if (renameat(dfd_, path.c_str(), target_dir.dfd_, target_path.c_str()) ==
  1455. -1) {
  1456. return PathError(errno, "Dir::Rename on '{0}' relative to '{1}'", path,
  1457. dfd_);
  1458. }
  1459. return Success();
  1460. }
  1461. inline auto DirRef::Chdir() -> ErrorOr<Success, FdError> {
  1462. if (fchdir(dfd_) == -1) {
  1463. return FdError(errno, "Dir::Chdir on '{0}'", dfd_);
  1464. }
  1465. return Success();
  1466. }
  1467. inline auto DirRef::Chdir(const std::filesystem::path& path)
  1468. -> ErrorOr<Success, PathError> {
  1469. if (path.is_absolute()) {
  1470. if (chdir(path.c_str()) == -1) {
  1471. return PathError(errno, "Dir::Chdir on '{0}' relative to '{1}'", path,
  1472. dfd_);
  1473. }
  1474. return Success();
  1475. }
  1476. CARBON_ASSIGN_OR_RETURN(Dir d, OpenDir(path));
  1477. auto result = d.Chdir();
  1478. if (result.ok()) {
  1479. return Success();
  1480. }
  1481. return PathError(result.error().unix_errnum(),
  1482. "Dir::Chdir on '{0}' relative to '{1}'", path, dfd_);
  1483. }
  1484. inline auto DirRef::Symlink(const std::filesystem::path& path,
  1485. const std::string& target)
  1486. -> ErrorOr<Success, PathError> {
  1487. if (symlinkat(target.c_str(), dfd_, path.c_str()) == -1) {
  1488. return PathError(errno, "Dir::Symlink on '{0}' relative to '{1}'", path,
  1489. dfd_);
  1490. }
  1491. return Success();
  1492. }
  1493. inline auto DirRef::Unlink(const std::filesystem::path& path)
  1494. -> ErrorOr<Success, PathError> {
  1495. if (unlinkat(dfd_, path.c_str(), /*flags=*/0) == -1) {
  1496. return PathError(errno, "Dir::Unlink on '{0}' relative to '{1}'", path,
  1497. dfd_);
  1498. }
  1499. return Success();
  1500. }
  1501. inline auto DirRef::Rmdir(const std::filesystem::path& path)
  1502. -> ErrorOr<Success, PathError> {
  1503. if (unlinkat(dfd_, path.c_str(), AT_REMOVEDIR) == -1) {
  1504. return PathError(errno, "Dir::Rmdir on '{0}' relative to '{1}'", path,
  1505. dfd_);
  1506. }
  1507. return Success();
  1508. }
  1509. template <OpenAccess A>
  1510. inline auto DirRef::OpenImpl(const std::filesystem::path& path,
  1511. CreationOptions creation_options,
  1512. ModeType creation_mode, OpenFlags flags)
  1513. -> ErrorOr<File<A>, PathError> {
  1514. for (;;) {
  1515. int fd = openat(dfd_, path.c_str(),
  1516. static_cast<int>(A) | static_cast<int>(creation_options) |
  1517. static_cast<int>(flags),
  1518. creation_mode);
  1519. if (fd == -1) {
  1520. // May need to retry on `EINTR` when opening FIFOs on Linux.
  1521. if (errno == EINTR) {
  1522. continue;
  1523. }
  1524. return PathError(errno, "Dir::Open on '{0}' relative to '{1}'", path,
  1525. dfd_);
  1526. }
  1527. return File<A>(fd);
  1528. }
  1529. }
  1530. constexpr Dir::~Dir() { Destroy(); }
  1531. inline auto Dir::TakeAndRead() && -> ErrorOr<Reader, FdError> {
  1532. // Transition our file descriptor into a directory stream, clearing it in the
  1533. // process.
  1534. int dfd = std::exchange(dfd_, -1);
  1535. DIR* dirp = fdopendir(dfd);
  1536. if (dirp == nullptr) {
  1537. return FdError(errno, "Dir::Read on '{0}'", dfd);
  1538. }
  1539. return Dir::Reader(dirp);
  1540. }
  1541. inline Dir::Dir(RemovingDir&& arg) noexcept : Dir(static_cast<Dir&&>(arg)) {
  1542. arg.path_.clear();
  1543. }
  1544. constexpr auto Dir::Destroy() -> void {
  1545. if (dfd_ != -1 && dfd_ != AT_FDCWD) {
  1546. auto result = close(dfd_);
  1547. // Closing a directory shouldn't produce errors, directly check fail on any.
  1548. //
  1549. // This is a very different case from `close` on a file producing an error.
  1550. // We don't actually write through the directory file descriptor, and for
  1551. // most platforms `closedir` (the closest thing in documentation and
  1552. // exclusively about directories), only provides a very few possible errors
  1553. // here:
  1554. //
  1555. // EBADF: This should be precluded by the types here, and so we consider
  1556. // it a programming error.
  1557. //
  1558. // EINTR: Technically, a system could fail here. We have good evidence
  1559. // that systems we practically support don't as there also is nothing
  1560. // useful to *do* in the face of this: retrying on almost all systems
  1561. // is not allowed as the file descriptor is immediately released. And
  1562. // here, there is no potentially dropped data to report.
  1563. //
  1564. // If we ever discover a platform that fails here, we should adjust this
  1565. // code to not fail in the face of that, likely by dropping the error. If we
  1566. // end up supporting a platform that actually requires well-specified
  1567. // retries, this code should handle that. Until then, we require these to
  1568. // succeed so we will learn about any issues during porting to new
  1569. // platforms.
  1570. CARBON_CHECK(result == 0, "{0}",
  1571. FdError(errno, "Dir::Destroy on '{0}'", dfd_));
  1572. }
  1573. dfd_ = -1;
  1574. }
  1575. inline RemovingDir::~RemovingDir() {
  1576. if (dfd_ != -1) {
  1577. auto result = std::move(*this).Remove();
  1578. CARBON_CHECK(result.ok(), "{0}", result.error());
  1579. }
  1580. }
  1581. inline auto RemovingDir::Remove() && -> ErrorOr<Success, PathError> {
  1582. CARBON_CHECK(dfd_ != -1,
  1583. "Unexpected explicit remove on a `RemovingDir` with no owned "
  1584. "directory!");
  1585. // Close the directory base object prior to removing it.
  1586. static_cast<Dir&>(*this) = Dir();
  1587. return Cwd().Rmtree(path_);
  1588. }
  1589. inline auto Dir::Iterator::operator++() -> Iterator& {
  1590. CARBON_CHECK(dirp_, "Cannot increment an end-iterator");
  1591. errno = 0;
  1592. entry_.dent_ = readdir(dirp_);
  1593. // There are no documented errors beyond an erroneous `dirp_` which would be
  1594. // a programming error and not due to any recoverable failure of the
  1595. // filesystem.
  1596. CARBON_CHECK(entry_.dent_ != nullptr || errno == 0,
  1597. "Using a directory iterator with a non-directory, errno '{0}'",
  1598. errno);
  1599. if (entry_.dent_ == nullptr) {
  1600. // Clear the directory pointer to ease debugging increments past the end.
  1601. dirp_ = nullptr;
  1602. }
  1603. return *this;
  1604. }
  1605. inline auto Dir::Reader::begin() -> Iterator {
  1606. // Reset the position of the directory stream to get the actual beginning.
  1607. rewinddir(dirp_);
  1608. return Iterator(dirp_);
  1609. }
  1610. inline auto Dir::Reader::end() -> Iterator { return Iterator(); }
  1611. inline auto Dir::Reader::Destroy() -> void {
  1612. if (dirp_) {
  1613. int result = closedir(dirp_);
  1614. // Closing a directory shouldn't produce interesting errors, so check fail
  1615. // on them directly.
  1616. //
  1617. // See the detailed comment on `Dir::Destroy` for more context on closing of
  1618. // directories, why we check-fail, and what we should do if we discover
  1619. // platforms where an error needs to be handled here.
  1620. CARBON_CHECK(result == 0, "{0}",
  1621. FdError(errno, "Dir::Reader::Destroy on '{0}'", dfd_));
  1622. dirp_ = nullptr;
  1623. dfd_ = -1;
  1624. }
  1625. }
  1626. } // namespace Carbon::Filesystem
  1627. #endif // CARBON_COMMON_FILESYSTEM_H_