1//===- llvm/Support/FileSystem.h - File System OS Concept -------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares the llvm::sys::fs namespace. It is designed after
11// TR2/boost filesystem (v3), but modified to remove exception handling and the
12// path class.
13//
14// All functions return an error_code and their actual work via the last out
15// argument. The out argument is defined if and only if errc::success is
16// returned. A function may return any error code in the generic or system
17// category. However, they shall be equivalent to any error conditions listed
18// in each functions respective documentation if the condition applies. [ note:
19// this does not guarantee that error_code will be in the set of explicitly
20// listed codes, but it does guarantee that if any of the explicitly listed
21// errors occur, the correct error_code will be used ]. All functions may
22// return errc::not_enough_memory if there is not enough memory to complete the
23// operation.
24//
25//===----------------------------------------------------------------------===//
26
27#ifndef LLVM_SUPPORT_FILESYSTEM_H
28#define LLVM_SUPPORT_FILESYSTEM_H
29
30#include "llvm/ADT/SmallString.h"
31#include "llvm/ADT/StringRef.h"
32#include "llvm/ADT/Twine.h"
33#include "llvm/Config/llvm-config.h"
34#include "llvm/Support/Chrono.h"
35#include "llvm/Support/Error.h"
36#include "llvm/Support/ErrorHandling.h"
37#include "llvm/Support/ErrorOr.h"
38#include "llvm/Support/MD5.h"
39#include <cassert>
40#include <cstdint>
41#include <ctime>
42#include <memory>
43#include <stack>
44#include <string>
45#include <system_error>
46#include <tuple>
47#include <vector>
48
49#ifdef HAVE_SYS_STAT_H
50#include <sys/stat.h>
51#endif
52
53namespace llvm {
54namespace sys {
55namespace fs {
56
57#if defined(_WIN32)
58// A Win32 HANDLE is a typedef of void*
59using file_t = void *;
60#else
61using file_t = int;
62#endif
63
64extern const file_t kInvalidFile;
65
66/// An enumeration for the file system's view of the type.
67enum class file_type {
68 status_error,
69 file_not_found,
70 regular_file,
71 directory_file,
72 symlink_file,
73 block_file,
74 character_file,
75 fifo_file,
76 socket_file,
77 type_unknown
78};
79
80/// space_info - Self explanatory.
81struct space_info {
82 uint64_t capacity;
83 uint64_t free;
84 uint64_t available;
85};
86
87enum perms {
88 no_perms = 0,
89 owner_read = 0400,
90 owner_write = 0200,
91 owner_exe = 0100,
92 owner_all = owner_read | owner_write | owner_exe,
93 group_read = 040,
94 group_write = 020,
95 group_exe = 010,
96 group_all = group_read | group_write | group_exe,
97 others_read = 04,
98 others_write = 02,
99 others_exe = 01,
100 others_all = others_read | others_write | others_exe,
101 all_read = owner_read | group_read | others_read,
102 all_write = owner_write | group_write | others_write,
103 all_exe = owner_exe | group_exe | others_exe,
104 all_all = owner_all | group_all | others_all,
105 set_uid_on_exe = 04000,
106 set_gid_on_exe = 02000,
107 sticky_bit = 01000,
108 all_perms = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit,
109 perms_not_known = 0xFFFF
110};
111
112// Helper functions so that you can use & and | to manipulate perms bits:
113inline perms operator|(perms l, perms r) {
114 return static_cast<perms>(static_cast<unsigned short>(l) |
115 static_cast<unsigned short>(r));
116}
117inline perms operator&(perms l, perms r) {
118 return static_cast<perms>(static_cast<unsigned short>(l) &
119 static_cast<unsigned short>(r));
120}
121inline perms &operator|=(perms &l, perms r) {
122 l = l | r;
123 return l;
124}
125inline perms &operator&=(perms &l, perms r) {
126 l = l & r;
127 return l;
128}
129inline perms operator~(perms x) {
130 // Avoid UB by explicitly truncating the (unsigned) ~ result.
131 return static_cast<perms>(
132 static_cast<unsigned short>(~static_cast<unsigned short>(x)));
133}
134
135class UniqueID {
136 uint64_t Device;
137 uint64_t File;
138
139public:
140 UniqueID() = default;
141 UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {}
142
143 bool operator==(const UniqueID &Other) const {
144 return Device == Other.Device && File == Other.File;
145 }
146 bool operator!=(const UniqueID &Other) const { return !(*this == Other); }
147 bool operator<(const UniqueID &Other) const {
148 return std::tie(Device, File) < std::tie(Other.Device, Other.File);
149 }
150
151 uint64_t getDevice() const { return Device; }
152 uint64_t getFile() const { return File; }
153};
154
155/// Represents the result of a call to directory_iterator::status(). This is a
156/// subset of the information returned by a regular sys::fs::status() call, and
157/// represents the information provided by Windows FileFirstFile/FindNextFile.
158class basic_file_status {
159protected:
160 #if defined(LLVM_ON_UNIX)
161 time_t fs_st_atime = 0;
162 time_t fs_st_mtime = 0;
163 uid_t fs_st_uid = 0;
164 gid_t fs_st_gid = 0;
165 off_t fs_st_size = 0;
166 #elif defined (_WIN32)
167 uint32_t LastAccessedTimeHigh = 0;
168 uint32_t LastAccessedTimeLow = 0;
169 uint32_t LastWriteTimeHigh = 0;
170 uint32_t LastWriteTimeLow = 0;
171 uint32_t FileSizeHigh = 0;
172 uint32_t FileSizeLow = 0;
173 #endif
174 file_type Type = file_type::status_error;
175 perms Perms = perms_not_known;
176
177public:
178 basic_file_status() = default;
179
180 explicit basic_file_status(file_type Type) : Type(Type) {}
181
182 #if defined(LLVM_ON_UNIX)
183 basic_file_status(file_type Type, perms Perms, time_t ATime, time_t MTime,
184 uid_t UID, gid_t GID, off_t Size)
185 : fs_st_atime(ATime), fs_st_mtime(MTime), fs_st_uid(UID), fs_st_gid(GID),
186 fs_st_size(Size), Type(Type), Perms(Perms) {}
187#elif defined(_WIN32)
188 basic_file_status(file_type Type, perms Perms, uint32_t LastAccessTimeHigh,
189 uint32_t LastAccessTimeLow, uint32_t LastWriteTimeHigh,
190 uint32_t LastWriteTimeLow, uint32_t FileSizeHigh,
191 uint32_t FileSizeLow)
192 : LastAccessedTimeHigh(LastAccessTimeHigh),
193 LastAccessedTimeLow(LastAccessTimeLow),
194 LastWriteTimeHigh(LastWriteTimeHigh),
195 LastWriteTimeLow(LastWriteTimeLow), FileSizeHigh(FileSizeHigh),
196 FileSizeLow(FileSizeLow), Type(Type), Perms(Perms) {}
197 #endif
198
199 // getters
200 file_type type() const { return Type; }
201 perms permissions() const { return Perms; }
202 TimePoint<> getLastAccessedTime() const;
203 TimePoint<> getLastModificationTime() const;
204
205 #if defined(LLVM_ON_UNIX)
206 uint32_t getUser() const { return fs_st_uid; }
207 uint32_t getGroup() const { return fs_st_gid; }
208 uint64_t getSize() const { return fs_st_size; }
209 #elif defined (_WIN32)
210 uint32_t getUser() const {
211 return 9999; // Not applicable to Windows, so...
212 }
213
214 uint32_t getGroup() const {
215 return 9999; // Not applicable to Windows, so...
216 }
217
218 uint64_t getSize() const {
219 return (uint64_t(FileSizeHigh) << 32) + FileSizeLow;
220 }
221 #endif
222
223 // setters
224 void type(file_type v) { Type = v; }
225 void permissions(perms p) { Perms = p; }
226};
227
228/// Represents the result of a call to sys::fs::status().
229class file_status : public basic_file_status {
230 friend bool equivalent(file_status A, file_status B);
231
232 #if defined(LLVM_ON_UNIX)
233 dev_t fs_st_dev = 0;
234 nlink_t fs_st_nlinks = 0;
235 ino_t fs_st_ino = 0;
236 #elif defined (_WIN32)
237 uint32_t NumLinks = 0;
238 uint32_t VolumeSerialNumber = 0;
239 uint32_t FileIndexHigh = 0;
240 uint32_t FileIndexLow = 0;
241 #endif
242
243public:
244 file_status() = default;
245
246 explicit file_status(file_type Type) : basic_file_status(Type) {}
247
248 #if defined(LLVM_ON_UNIX)
249 file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino,
250 time_t ATime, time_t MTime, uid_t UID, gid_t GID, off_t Size)
251 : basic_file_status(Type, Perms, ATime, MTime, UID, GID, Size),
252 fs_st_dev(Dev), fs_st_nlinks(Links), fs_st_ino(Ino) {}
253 #elif defined(_WIN32)
254 file_status(file_type Type, perms Perms, uint32_t LinkCount,
255 uint32_t LastAccessTimeHigh, uint32_t LastAccessTimeLow,
256 uint32_t LastWriteTimeHigh, uint32_t LastWriteTimeLow,
257 uint32_t VolumeSerialNumber, uint32_t FileSizeHigh,
258 uint32_t FileSizeLow, uint32_t FileIndexHigh,
259 uint32_t FileIndexLow)
260 : basic_file_status(Type, Perms, LastAccessTimeHigh, LastAccessTimeLow,
261 LastWriteTimeHigh, LastWriteTimeLow, FileSizeHigh,
262 FileSizeLow),
263 NumLinks(LinkCount), VolumeSerialNumber(VolumeSerialNumber),
264 FileIndexHigh(FileIndexHigh), FileIndexLow(FileIndexLow) {}
265 #endif
266
267 UniqueID getUniqueID() const;
268 uint32_t getLinkCount() const;
269};
270
271/// @}
272/// @name Physical Operators
273/// @{
274
275/// Make \a path an absolute path.
276///
277/// Makes \a path absolute using the \a current_directory if it is not already.
278/// An empty \a path will result in the \a current_directory.
279///
280/// /absolute/path => /absolute/path
281/// relative/../path => <current-directory>/relative/../path
282///
283/// @param path A path that is modified to be an absolute path.
284/// @returns errc::success if \a path has been made absolute, otherwise a
285/// platform-specific error_code.
286std::error_code make_absolute(const Twine &current_directory,
287 SmallVectorImpl<char> &path);
288
289/// Make \a path an absolute path.
290///
291/// Makes \a path absolute using the current directory if it is not already. An
292/// empty \a path will result in the current directory.
293///
294/// /absolute/path => /absolute/path
295/// relative/../path => <current-directory>/relative/../path
296///
297/// @param path A path that is modified to be an absolute path.
298/// @returns errc::success if \a path has been made absolute, otherwise a
299/// platform-specific error_code.
300std::error_code make_absolute(SmallVectorImpl<char> &path);
301
302/// Create all the non-existent directories in path.
303///
304/// @param path Directories to create.
305/// @returns errc::success if is_directory(path), otherwise a platform
306/// specific error_code. If IgnoreExisting is false, also returns
307/// error if the directory already existed.
308std::error_code create_directories(const Twine &path,
309 bool IgnoreExisting = true,
310 perms Perms = owner_all | group_all);
311
312/// Create the directory in path.
313///
314/// @param path Directory to create.
315/// @returns errc::success if is_directory(path), otherwise a platform
316/// specific error_code. If IgnoreExisting is false, also returns
317/// error if the directory already existed.
318std::error_code create_directory(const Twine &path, bool IgnoreExisting = true,
319 perms Perms = owner_all | group_all);
320
321/// Create a link from \a from to \a to.
322///
323/// The link may be a soft or a hard link, depending on the platform. The caller
324/// may not assume which one. Currently on windows it creates a hard link since
325/// soft links require extra privileges. On unix, it creates a soft link since
326/// hard links don't work on SMB file systems.
327///
328/// @param to The path to hard link to.
329/// @param from The path to hard link from. This is created.
330/// @returns errc::success if the link was created, otherwise a platform
331/// specific error_code.
332std::error_code create_link(const Twine &to, const Twine &from);
333
334/// Create a hard link from \a from to \a to, or return an error.
335///
336/// @param to The path to hard link to.
337/// @param from The path to hard link from. This is created.
338/// @returns errc::success if the link was created, otherwise a platform
339/// specific error_code.
340std::error_code create_hard_link(const Twine &to, const Twine &from);
341
342/// Collapse all . and .. patterns, resolve all symlinks, and optionally
343/// expand ~ expressions to the user's home directory.
344///
345/// @param path The path to resolve.
346/// @param output The location to store the resolved path.
347/// @param expand_tilde If true, resolves ~ expressions to the user's home
348/// directory.
349std::error_code real_path(const Twine &path, SmallVectorImpl<char> &output,
350 bool expand_tilde = false);
351
352/// Expands ~ expressions to the user's home directory. On Unix ~user
353/// directories are resolved as well.
354///
355/// @param path The path to resolve.
356void expand_tilde(const Twine &path, SmallVectorImpl<char> &output);
357
358/// Get the current path.
359///
360/// @param result Holds the current path on return.
361/// @returns errc::success if the current path has been stored in result,
362/// otherwise a platform-specific error_code.
363std::error_code current_path(SmallVectorImpl<char> &result);
364
365/// Set the current path.
366///
367/// @param path The path to set.
368/// @returns errc::success if the current path was successfully set,
369/// otherwise a platform-specific error_code.
370std::error_code set_current_path(const Twine &path);
371
372/// Remove path. Equivalent to POSIX remove().
373///
374/// @param path Input path.
375/// @returns errc::success if path has been removed or didn't exist, otherwise a
376/// platform-specific error code. If IgnoreNonExisting is false, also
377/// returns error if the file didn't exist.
378std::error_code remove(const Twine &path, bool IgnoreNonExisting = true);
379
380/// Recursively delete a directory.
381///
382/// @param path Input path.
383/// @returns errc::success if path has been removed or didn't exist, otherwise a
384/// platform-specific error code.
385std::error_code remove_directories(const Twine &path, bool IgnoreErrors = true);
386
387/// Rename \a from to \a to.
388///
389/// Files are renamed as if by POSIX rename(), except that on Windows there may
390/// be a short interval of time during which the destination file does not
391/// exist.
392///
393/// @param from The path to rename from.
394/// @param to The path to rename to. This is created.
395std::error_code rename(const Twine &from, const Twine &to);
396
397/// Copy the contents of \a From to \a To.
398///
399/// @param From The path to copy from.
400/// @param To The path to copy to. This is created.
401std::error_code copy_file(const Twine &From, const Twine &To);
402
403/// Copy the contents of \a From to \a To.
404///
405/// @param From The path to copy from.
406/// @param ToFD The open file descriptor of the destination file.
407std::error_code copy_file(const Twine &From, int ToFD);
408
409/// Resize path to size. File is resized as if by POSIX truncate().
410///
411/// @param FD Input file descriptor.
412/// @param Size Size to resize to.
413/// @returns errc::success if \a path has been resized to \a size, otherwise a
414/// platform-specific error_code.
415std::error_code resize_file(int FD, uint64_t Size);
416
417/// Compute an MD5 hash of a file's contents.
418///
419/// @param FD Input file descriptor.
420/// @returns An MD5Result with the hash computed, if successful, otherwise a
421/// std::error_code.
422ErrorOr<MD5::MD5Result> md5_contents(int FD);
423
424/// Version of compute_md5 that doesn't require an open file descriptor.
425ErrorOr<MD5::MD5Result> md5_contents(const Twine &Path);
426
427/// @}
428/// @name Physical Observers
429/// @{
430
431/// Does file exist?
432///
433/// @param status A basic_file_status previously returned from stat.
434/// @returns True if the file represented by status exists, false if it does
435/// not.
436bool exists(const basic_file_status &status);
437
438enum class AccessMode { Exist, Write, Execute };
439
440/// Can the file be accessed?
441///
442/// @param Path Input path.
443/// @returns errc::success if the path can be accessed, otherwise a
444/// platform-specific error_code.
445std::error_code access(const Twine &Path, AccessMode Mode);
446
447/// Does file exist?
448///
449/// @param Path Input path.
450/// @returns True if it exists, false otherwise.
451inline bool exists(const Twine &Path) {
452 return !access(Path, AccessMode::Exist);
453}
454
455/// Can we execute this file?
456///
457/// @param Path Input path.
458/// @returns True if we can execute it, false otherwise.
459bool can_execute(const Twine &Path);
460
461/// Can we write this file?
462///
463/// @param Path Input path.
464/// @returns True if we can write to it, false otherwise.
465inline bool can_write(const Twine &Path) {
466 return !access(Path, AccessMode::Write);
467}
468
469/// Do file_status's represent the same thing?
470///
471/// @param A Input file_status.
472/// @param B Input file_status.
473///
474/// assert(status_known(A) || status_known(B));
475///
476/// @returns True if A and B both represent the same file system entity, false
477/// otherwise.
478bool equivalent(file_status A, file_status B);
479
480/// Do paths represent the same thing?
481///
482/// assert(status_known(A) || status_known(B));
483///
484/// @param A Input path A.
485/// @param B Input path B.
486/// @param result Set to true if stat(A) and stat(B) have the same device and
487/// inode (or equivalent).
488/// @returns errc::success if result has been successfully set, otherwise a
489/// platform-specific error_code.
490std::error_code equivalent(const Twine &A, const Twine &B, bool &result);
491
492/// Simpler version of equivalent for clients that don't need to
493/// differentiate between an error and false.
494inline bool equivalent(const Twine &A, const Twine &B) {
495 bool result;
496 return !equivalent(A, B, result) && result;
497}
498
499/// Is the file mounted on a local filesystem?
500///
501/// @param path Input path.
502/// @param result Set to true if \a path is on fixed media such as a hard disk,
503/// false if it is not.
504/// @returns errc::success if result has been successfully set, otherwise a
505/// platform specific error_code.
506std::error_code is_local(const Twine &path, bool &result);
507
508/// Version of is_local accepting an open file descriptor.
509std::error_code is_local(int FD, bool &result);
510
511/// Simpler version of is_local for clients that don't need to
512/// differentiate between an error and false.
513inline bool is_local(const Twine &Path) {
514 bool Result;
515 return !is_local(Path, Result) && Result;
516}
517
518/// Simpler version of is_local accepting an open file descriptor for
519/// clients that don't need to differentiate between an error and false.
520inline bool is_local(int FD) {
521 bool Result;
522 return !is_local(FD, Result) && Result;
523}
524
525/// Does status represent a directory?
526///
527/// @param Path The path to get the type of.
528/// @param Follow For symbolic links, indicates whether to return the file type
529/// of the link itself, or of the target.
530/// @returns A value from the file_type enumeration indicating the type of file.
531file_type get_file_type(const Twine &Path, bool Follow = true);
532
533/// Does status represent a directory?
534///
535/// @param status A basic_file_status previously returned from status.
536/// @returns status.type() == file_type::directory_file.
537bool is_directory(const basic_file_status &status);
538
539/// Is path a directory?
540///
541/// @param path Input path.
542/// @param result Set to true if \a path is a directory (after following
543/// symlinks, false if it is not. Undefined otherwise.
544/// @returns errc::success if result has been successfully set, otherwise a
545/// platform-specific error_code.
546std::error_code is_directory(const Twine &path, bool &result);
547
548/// Simpler version of is_directory for clients that don't need to
549/// differentiate between an error and false.
550inline bool is_directory(const Twine &Path) {
551 bool Result;
552 return !is_directory(Path, Result) && Result;
553}
554
555/// Does status represent a regular file?
556///
557/// @param status A basic_file_status previously returned from status.
558/// @returns status_known(status) && status.type() == file_type::regular_file.
559bool is_regular_file(const basic_file_status &status);
560
561/// Is path a regular file?
562///
563/// @param path Input path.
564/// @param result Set to true if \a path is a regular file (after following
565/// symlinks), false if it is not. Undefined otherwise.
566/// @returns errc::success if result has been successfully set, otherwise a
567/// platform-specific error_code.
568std::error_code is_regular_file(const Twine &path, bool &result);
569
570/// Simpler version of is_regular_file for clients that don't need to
571/// differentiate between an error and false.
572inline bool is_regular_file(const Twine &Path) {
573 bool Result;
574 if (is_regular_file(Path, Result))
575 return false;
576 return Result;
577}
578
579/// Does status represent a symlink file?
580///
581/// @param status A basic_file_status previously returned from status.
582/// @returns status_known(status) && status.type() == file_type::symlink_file.
583bool is_symlink_file(const basic_file_status &status);
584
585/// Is path a symlink file?
586///
587/// @param path Input path.
588/// @param result Set to true if \a path is a symlink file, false if it is not.
589/// Undefined otherwise.
590/// @returns errc::success if result has been successfully set, otherwise a
591/// platform-specific error_code.
592std::error_code is_symlink_file(const Twine &path, bool &result);
593
594/// Simpler version of is_symlink_file for clients that don't need to
595/// differentiate between an error and false.
596inline bool is_symlink_file(const Twine &Path) {
597 bool Result;
598 if (is_symlink_file(Path, Result))
599 return false;
600 return Result;
601}
602
603/// Does this status represent something that exists but is not a
604/// directory or regular file?
605///
606/// @param status A basic_file_status previously returned from status.
607/// @returns exists(s) && !is_regular_file(s) && !is_directory(s)
608bool is_other(const basic_file_status &status);
609
610/// Is path something that exists but is not a directory,
611/// regular file, or symlink?
612///
613/// @param path Input path.
614/// @param result Set to true if \a path exists, but is not a directory, regular
615/// file, or a symlink, false if it does not. Undefined otherwise.
616/// @returns errc::success if result has been successfully set, otherwise a
617/// platform-specific error_code.
618std::error_code is_other(const Twine &path, bool &result);
619
620/// Get file status as if by POSIX stat().
621///
622/// @param path Input path.
623/// @param result Set to the file status.
624/// @param follow When true, follows symlinks. Otherwise, the symlink itself is
625/// statted.
626/// @returns errc::success if result has been successfully set, otherwise a
627/// platform-specific error_code.
628std::error_code status(const Twine &path, file_status &result,
629 bool follow = true);
630
631/// A version for when a file descriptor is already available.
632std::error_code status(int FD, file_status &Result);
633
634/// Set file permissions.
635///
636/// @param Path File to set permissions on.
637/// @param Permissions New file permissions.
638/// @returns errc::success if the permissions were successfully set, otherwise
639/// a platform-specific error_code.
640/// @note On Windows, all permissions except *_write are ignored. Using any of
641/// owner_write, group_write, or all_write will make the file writable.
642/// Otherwise, the file will be marked as read-only.
643std::error_code setPermissions(const Twine &Path, perms Permissions);
644
645/// Get file permissions.
646///
647/// @param Path File to get permissions from.
648/// @returns the permissions if they were successfully retrieved, otherwise a
649/// platform-specific error_code.
650/// @note On Windows, if the file does not have the FILE_ATTRIBUTE_READONLY
651/// attribute, all_all will be returned. Otherwise, all_read | all_exe
652/// will be returned.
653ErrorOr<perms> getPermissions(const Twine &Path);
654
655/// Get file size.
656///
657/// @param Path Input path.
658/// @param Result Set to the size of the file in \a Path.
659/// @returns errc::success if result has been successfully set, otherwise a
660/// platform-specific error_code.
661inline std::error_code file_size(const Twine &Path, uint64_t &Result) {
662 file_status Status;
663 std::error_code EC = status(Path, Status);
664 if (EC)
665 return EC;
666 Result = Status.getSize();
667 return std::error_code();
668}
669
670/// Set the file modification and access time.
671///
672/// @returns errc::success if the file times were successfully set, otherwise a
673/// platform-specific error_code or errc::function_not_supported on
674/// platforms where the functionality isn't available.
675std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
676 TimePoint<> ModificationTime);
677
678/// Simpler version that sets both file modification and access time to the same
679/// time.
680inline std::error_code setLastAccessAndModificationTime(int FD,
681 TimePoint<> Time) {
682 return setLastAccessAndModificationTime(FD, Time, Time);
683}
684
685/// Is status available?
686///
687/// @param s Input file status.
688/// @returns True if status() != status_error.
689bool status_known(const basic_file_status &s);
690
691/// Is status available?
692///
693/// @param path Input path.
694/// @param result Set to true if status() != status_error.
695/// @returns errc::success if result has been successfully set, otherwise a
696/// platform-specific error_code.
697std::error_code status_known(const Twine &path, bool &result);
698
699enum CreationDisposition : unsigned {
700 /// CD_CreateAlways - When opening a file:
701 /// * If it already exists, truncate it.
702 /// * If it does not already exist, create a new file.
703 CD_CreateAlways = 0,
704
705 /// CD_CreateNew - When opening a file:
706 /// * If it already exists, fail.
707 /// * If it does not already exist, create a new file.
708 CD_CreateNew = 1,
709
710 /// CD_OpenExisting - When opening a file:
711 /// * If it already exists, open the file with the offset set to 0.
712 /// * If it does not already exist, fail.
713 CD_OpenExisting = 2,
714
715 /// CD_OpenAlways - When opening a file:
716 /// * If it already exists, open the file with the offset set to 0.
717 /// * If it does not already exist, create a new file.
718 CD_OpenAlways = 3,
719};
720
721enum FileAccess : unsigned {
722 FA_Read = 1,
723 FA_Write = 2,
724};
725
726enum OpenFlags : unsigned {
727 OF_None = 0,
728 F_None = 0, // For compatibility
729
730 /// The file should be opened in text mode on platforms that make this
731 /// distinction.
732 OF_Text = 1,
733 F_Text = 1, // For compatibility
734
735 /// The file should be opened in append mode.
736 OF_Append = 2,
737 F_Append = 2, // For compatibility
738
739 /// Delete the file on close. Only makes a difference on windows.
740 OF_Delete = 4,
741
742 /// When a child process is launched, this file should remain open in the
743 /// child process.
744 OF_ChildInherit = 8,
745
746 /// Force files Atime to be updated on access. Only makes a difference on windows.
747 OF_UpdateAtime = 16,
748};
749
750/// Create a uniquely named file.
751///
752/// Generates a unique path suitable for a temporary file and then opens it as a
753/// file. The name is based on \a model with '%' replaced by a random char in
754/// [0-9a-f]. If \a model is not an absolute path, the temporary file will be
755/// created in the current directory.
756///
757/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s
758///
759/// This is an atomic operation. Either the file is created and opened, or the
760/// file system is left untouched.
761///
762/// The intended use is for files that are to be kept, possibly after
763/// renaming them. For example, when running 'clang -c foo.o', the file can
764/// be first created as foo-abc123.o and then renamed.
765///
766/// @param Model Name to base unique path off of.
767/// @param ResultFD Set to the opened file's file descriptor.
768/// @param ResultPath Set to the opened file's absolute path.
769/// @returns errc::success if Result{FD,Path} have been successfully set,
770/// otherwise a platform-specific error_code.
771std::error_code createUniqueFile(const Twine &Model, int &ResultFD,
772 SmallVectorImpl<char> &ResultPath,
773 unsigned Mode = all_read | all_write);
774
775/// Simpler version for clients that don't want an open file. An empty
776/// file will still be created.
777std::error_code createUniqueFile(const Twine &Model,
778 SmallVectorImpl<char> &ResultPath,
779 unsigned Mode = all_read | all_write);
780
781/// Represents a temporary file.
782///
783/// The temporary file must be eventually discarded or given a final name and
784/// kept.
785///
786/// The destructor doesn't implicitly discard because there is no way to
787/// properly handle errors in a destructor.
788class TempFile {
789 bool Done = false;
790 TempFile(StringRef Name, int FD);
791
792public:
793 /// This creates a temporary file with createUniqueFile and schedules it for
794 /// deletion with sys::RemoveFileOnSignal.
795 static Expected<TempFile> create(const Twine &Model,
796 unsigned Mode = all_read | all_write);
797 TempFile(TempFile &&Other);
798 TempFile &operator=(TempFile &&Other);
799
800 // Name of the temporary file.
801 std::string TmpName;
802
803 // The open file descriptor.
804 int FD = -1;
805
806 // Keep this with the given name.
807 Error keep(const Twine &Name);
808
809 // Keep this with the temporary name.
810 Error keep();
811
812 // Delete the file.
813 Error discard();
814
815 // This checks that keep or delete was called.
816 ~TempFile();
817};
818
819/// Create a file in the system temporary directory.
820///
821/// The filename is of the form prefix-random_chars.suffix. Since the directory
822/// is not know to the caller, Prefix and Suffix cannot have path separators.
823/// The files are created with mode 0600.
824///
825/// This should be used for things like a temporary .s that is removed after
826/// running the assembler.
827std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
828 int &ResultFD,
829 SmallVectorImpl<char> &ResultPath);
830
831/// Simpler version for clients that don't want an open file. An empty
832/// file will still be created.
833std::error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix,
834 SmallVectorImpl<char> &ResultPath);
835
836std::error_code createUniqueDirectory(const Twine &Prefix,
837 SmallVectorImpl<char> &ResultPath);
838
839/// Get a unique name, not currently exisiting in the filesystem. Subject
840/// to race conditions, prefer to use createUniqueFile instead.
841///
842/// Similar to createUniqueFile, but instead of creating a file only
843/// checks if it exists. This function is subject to race conditions, if you
844/// want to use the returned name to actually create a file, use
845/// createUniqueFile instead.
846std::error_code getPotentiallyUniqueFileName(const Twine &Model,
847 SmallVectorImpl<char> &ResultPath);
848
849/// Get a unique temporary file name, not currently exisiting in the
850/// filesystem. Subject to race conditions, prefer to use createTemporaryFile
851/// instead.
852///
853/// Similar to createTemporaryFile, but instead of creating a file only
854/// checks if it exists. This function is subject to race conditions, if you
855/// want to use the returned name to actually create a file, use
856/// createTemporaryFile instead.
857std::error_code
858getPotentiallyUniqueTempFileName(const Twine &Prefix, StringRef Suffix,
859 SmallVectorImpl<char> &ResultPath);
860
861inline OpenFlags operator|(OpenFlags A, OpenFlags B) {
862 return OpenFlags(unsigned(A) | unsigned(B));
863}
864
865inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) {
866 A = A | B;
867 return A;
868}
869
870inline FileAccess operator|(FileAccess A, FileAccess B) {
871 return FileAccess(unsigned(A) | unsigned(B));
872}
873
874inline FileAccess &operator|=(FileAccess &A, FileAccess B) {
875 A = A | B;
876 return A;
877}
878
879/// @brief Opens a file with the specified creation disposition, access mode,
880/// and flags and returns a file descriptor.
881///
882/// The caller is responsible for closing the file descriptor once they are
883/// finished with it.
884///
885/// @param Name The path of the file to open, relative or absolute.
886/// @param ResultFD If the file could be opened successfully, its descriptor
887/// is stored in this location. Otherwise, this is set to -1.
888/// @param Disp Value specifying the existing-file behavior.
889/// @param Access Value specifying whether to open the file in read, write, or
890/// read-write mode.
891/// @param Flags Additional flags.
892/// @param Mode The access permissions of the file, represented in octal.
893/// @returns errc::success if \a Name has been opened, otherwise a
894/// platform-specific error_code.
895std::error_code openFile(const Twine &Name, int &ResultFD,
896 CreationDisposition Disp, FileAccess Access,
897 OpenFlags Flags, unsigned Mode = 0666);
898
899/// @brief Opens a file with the specified creation disposition, access mode,
900/// and flags and returns a platform-specific file object.
901///
902/// The caller is responsible for closing the file object once they are
903/// finished with it.
904///
905/// @param Name The path of the file to open, relative or absolute.
906/// @param Disp Value specifying the existing-file behavior.
907/// @param Access Value specifying whether to open the file in read, write, or
908/// read-write mode.
909/// @param Flags Additional flags.
910/// @param Mode The access permissions of the file, represented in octal.
911/// @returns errc::success if \a Name has been opened, otherwise a
912/// platform-specific error_code.
913Expected<file_t> openNativeFile(const Twine &Name, CreationDisposition Disp,
914 FileAccess Access, OpenFlags Flags,
915 unsigned Mode = 0666);
916
917/// @brief Opens the file with the given name in a write-only or read-write
918/// mode, returning its open file descriptor. If the file does not exist, it
919/// is created.
920///
921/// The caller is responsible for closing the file descriptor once they are
922/// finished with it.
923///
924/// @param Name The path of the file to open, relative or absolute.
925/// @param ResultFD If the file could be opened successfully, its descriptor
926/// is stored in this location. Otherwise, this is set to -1.
927/// @param Flags Additional flags used to determine whether the file should be
928/// opened in, for example, read-write or in write-only mode.
929/// @param Mode The access permissions of the file, represented in octal.
930/// @returns errc::success if \a Name has been opened, otherwise a
931/// platform-specific error_code.
932inline std::error_code
933openFileForWrite(const Twine &Name, int &ResultFD,
934 CreationDisposition Disp = CD_CreateAlways,
935 OpenFlags Flags = OF_None, unsigned Mode = 0666) {
936 return openFile(Name, ResultFD, Disp, FA_Write, Flags, Mode);
937}
938
939/// @brief Opens the file with the given name in a write-only or read-write
940/// mode, returning its open file descriptor. If the file does not exist, it
941/// is created.
942///
943/// The caller is responsible for closing the freeing the file once they are
944/// finished with it.
945///
946/// @param Name The path of the file to open, relative or absolute.
947/// @param Flags Additional flags used to determine whether the file should be
948/// opened in, for example, read-write or in write-only mode.
949/// @param Mode The access permissions of the file, represented in octal.
950/// @returns a platform-specific file descriptor if \a Name has been opened,
951/// otherwise an error object.
952inline Expected<file_t> openNativeFileForWrite(const Twine &Name,
953 CreationDisposition Disp,
954 OpenFlags Flags,
955 unsigned Mode = 0666) {
956 return openNativeFile(Name, Disp, FA_Write, Flags, Mode);
957}
958
959/// @brief Opens the file with the given name in a write-only or read-write
960/// mode, returning its open file descriptor. If the file does not exist, it
961/// is created.
962///
963/// The caller is responsible for closing the file descriptor once they are
964/// finished with it.
965///
966/// @param Name The path of the file to open, relative or absolute.
967/// @param ResultFD If the file could be opened successfully, its descriptor
968/// is stored in this location. Otherwise, this is set to -1.
969/// @param Flags Additional flags used to determine whether the file should be
970/// opened in, for example, read-write or in write-only mode.
971/// @param Mode The access permissions of the file, represented in octal.
972/// @returns errc::success if \a Name has been opened, otherwise a
973/// platform-specific error_code.
974inline std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD,
975 CreationDisposition Disp,
976 OpenFlags Flags,
977 unsigned Mode = 0666) {
978 return openFile(Name, ResultFD, Disp, FA_Write | FA_Read, Flags, Mode);
979}
980
981/// @brief Opens the file with the given name in a write-only or read-write
982/// mode, returning its open file descriptor. If the file does not exist, it
983/// is created.
984///
985/// The caller is responsible for closing the freeing the file once they are
986/// finished with it.
987///
988/// @param Name The path of the file to open, relative or absolute.
989/// @param Flags Additional flags used to determine whether the file should be
990/// opened in, for example, read-write or in write-only mode.
991/// @param Mode The access permissions of the file, represented in octal.
992/// @returns a platform-specific file descriptor if \a Name has been opened,
993/// otherwise an error object.
994inline Expected<file_t> openNativeFileForReadWrite(const Twine &Name,
995 CreationDisposition Disp,
996 OpenFlags Flags,
997 unsigned Mode = 0666) {
998 return openNativeFile(Name, Disp, FA_Write | FA_Read, Flags, Mode);
999}
1000
1001/// @brief Opens the file with the given name in a read-only mode, returning
1002/// its open file descriptor.
1003///
1004/// The caller is responsible for closing the file descriptor once they are
1005/// finished with it.
1006///
1007/// @param Name The path of the file to open, relative or absolute.
1008/// @param ResultFD If the file could be opened successfully, its descriptor
1009/// is stored in this location. Otherwise, this is set to -1.
1010/// @param RealPath If nonnull, extra work is done to determine the real path
1011/// of the opened file, and that path is stored in this
1012/// location.
1013/// @returns errc::success if \a Name has been opened, otherwise a
1014/// platform-specific error_code.
1015std::error_code openFileForRead(const Twine &Name, int &ResultFD,
1016 OpenFlags Flags = OF_None,
1017 SmallVectorImpl<char> *RealPath = nullptr);
1018
1019/// @brief Opens the file with the given name in a read-only mode, returning
1020/// its open file descriptor.
1021///
1022/// The caller is responsible for closing the freeing the file once they are
1023/// finished with it.
1024///
1025/// @param Name The path of the file to open, relative or absolute.
1026/// @param RealPath If nonnull, extra work is done to determine the real path
1027/// of the opened file, and that path is stored in this
1028/// location.
1029/// @returns a platform-specific file descriptor if \a Name has been opened,
1030/// otherwise an error object.
1031Expected<file_t>
1032openNativeFileForRead(const Twine &Name, OpenFlags Flags = OF_None,
1033 SmallVectorImpl<char> *RealPath = nullptr);
1034
1035/// @brief Close the file object. This should be used instead of ::close for
1036/// portability.
1037///
1038/// @param F On input, this is the file to close. On output, the file is
1039/// set to kInvalidFile.
1040void closeFile(file_t &F);
1041
1042std::error_code getUniqueID(const Twine Path, UniqueID &Result);
1043
1044/// Get disk space usage information.
1045///
1046/// Note: Users must be careful about "Time Of Check, Time Of Use" kind of bug.
1047/// Note: Windows reports results according to the quota allocated to the user.
1048///
1049/// @param Path Input path.
1050/// @returns a space_info structure filled with the capacity, free, and
1051/// available space on the device \a Path is on. A platform specific error_code
1052/// is returned on error.
1053ErrorOr<space_info> disk_space(const Twine &Path);
1054
1055/// This class represents a memory mapped file. It is based on
1056/// boost::iostreams::mapped_file.
1057class mapped_file_region {
1058public:
1059 enum mapmode {
1060 readonly, ///< May only access map via const_data as read only.
1061 readwrite, ///< May access map via data and modify it. Written to path.
1062 priv ///< May modify via data, but changes are lost on destruction.
1063 };
1064
1065private:
1066 /// Platform-specific mapping state.
1067 size_t Size;
1068 void *Mapping;
1069#ifdef _WIN32
1070 void *FileHandle;
1071#endif
1072 mapmode Mode;
1073
1074 std::error_code init(int FD, uint64_t Offset, mapmode Mode);
1075
1076public:
1077 mapped_file_region() = delete;
1078 mapped_file_region(mapped_file_region&) = delete;
1079 mapped_file_region &operator =(mapped_file_region&) = delete;
1080
1081 /// \param fd An open file descriptor to map. mapped_file_region takes
1082 /// ownership if closefd is true. It must have been opended in the correct
1083 /// mode.
1084 mapped_file_region(int fd, mapmode mode, size_t length, uint64_t offset,
1085 std::error_code &ec);
1086
1087 ~mapped_file_region();
1088
1089 size_t size() const;
1090 char *data() const;
1091
1092 /// Get a const view of the data. Modifying this memory has undefined
1093 /// behavior.
1094 const char *const_data() const;
1095
1096 /// \returns The minimum alignment offset must be.
1097 static int alignment();
1098};
1099
1100/// Return the path to the main executable, given the value of argv[0] from
1101/// program startup and the address of main itself. In extremis, this function
1102/// may fail and return an empty path.
1103std::string getMainExecutable(const char *argv0, void *MainExecAddr);
1104
1105/// @}
1106/// @name Iterators
1107/// @{
1108
1109/// directory_entry - A single entry in a directory.
1110class directory_entry {
1111 // FIXME: different platforms make different information available "for free"
1112 // when traversing a directory. The design of this class wraps most of the
1113 // information in basic_file_status, so on platforms where we can't populate
1114 // that whole structure, callers end up paying for a stat().
1115 // std::filesystem::directory_entry may be a better model.
1116 std::string Path;
1117 file_type Type; // Most platforms can provide this.
1118 bool FollowSymlinks; // Affects the behavior of status().
1119 basic_file_status Status; // If available.
1120
1121public:
1122 explicit directory_entry(const Twine &Path, bool FollowSymlinks = true,
1123 file_type Type = file_type::type_unknown,
1124 basic_file_status Status = basic_file_status())
1125 : Path(Path.str()), Type(Type), FollowSymlinks(FollowSymlinks),
1126 Status(Status) {}
1127
1128 directory_entry() = default;
1129
1130 void replace_filename(const Twine &Filename, file_type Type,
1131 basic_file_status Status = basic_file_status());
1132
1133 const std::string &path() const { return Path; }
1134 // Get basic information about entry file (a subset of fs::status()).
1135 // On most platforms this is a stat() call.
1136 // On windows the information was already retrieved from the directory.
1137 ErrorOr<basic_file_status> status() const;
1138 // Get the type of this file.
1139 // On most platforms (Linux/Mac/Windows/BSD), this was already retrieved.
1140 // On some platforms (e.g. Solaris) this is a stat() call.
1141 file_type type() const {
1142 if (Type != file_type::type_unknown)
1143 return Type;
1144 auto S = status();
1145 return S ? S->type() : file_type::type_unknown;
1146 }
1147
1148 bool operator==(const directory_entry& RHS) const { return Path == RHS.Path; }
1149 bool operator!=(const directory_entry& RHS) const { return !(*this == RHS); }
1150 bool operator< (const directory_entry& RHS) const;
1151 bool operator<=(const directory_entry& RHS) const;
1152 bool operator> (const directory_entry& RHS) const;
1153 bool operator>=(const directory_entry& RHS) const;
1154};
1155
1156namespace detail {
1157
1158 struct DirIterState;
1159
1160 std::error_code directory_iterator_construct(DirIterState &, StringRef, bool);
1161 std::error_code directory_iterator_increment(DirIterState &);
1162 std::error_code directory_iterator_destruct(DirIterState &);
1163
1164 /// Keeps state for the directory_iterator.
1165 struct DirIterState {
1166 ~DirIterState() {
1167 directory_iterator_destruct(*this);
1168 }
1169
1170 intptr_t IterationHandle = 0;
1171 directory_entry CurrentEntry;
1172 };
1173
1174} // end namespace detail
1175
1176/// directory_iterator - Iterates through the entries in path. There is no
1177/// operator++ because we need an error_code. If it's really needed we can make
1178/// it call report_fatal_error on error.
1179class directory_iterator {
1180 std::shared_ptr<detail::DirIterState> State;
1181 bool FollowSymlinks = true;
1182
1183public:
1184 explicit directory_iterator(const Twine &path, std::error_code &ec,
1185 bool follow_symlinks = true)
1186 : FollowSymlinks(follow_symlinks) {
1187 State = std::make_shared<detail::DirIterState>();
1188 SmallString<128> path_storage;
1189 ec = detail::directory_iterator_construct(
1190 *State, path.toStringRef(path_storage), FollowSymlinks);
1191 }
1192
1193 explicit directory_iterator(const directory_entry &de, std::error_code &ec,
1194 bool follow_symlinks = true)
1195 : FollowSymlinks(follow_symlinks) {
1196 State = std::make_shared<detail::DirIterState>();
1197 ec = detail::directory_iterator_construct(
1198 *State, de.path(), FollowSymlinks);
1199 }
1200
1201 /// Construct end iterator.
1202 directory_iterator() = default;
1203
1204 // No operator++ because we need error_code.
1205 directory_iterator &increment(std::error_code &ec) {
1206 ec = directory_iterator_increment(*State);
1207 return *this;
1208 }
1209
1210 const directory_entry &operator*() const { return State->CurrentEntry; }
1211 const directory_entry *operator->() const { return &State->CurrentEntry; }
1212
1213 bool operator==(const directory_iterator &RHS) const {
1214 if (State == RHS.State)
1215 return true;
1216 if (!RHS.State)
1217 return State->CurrentEntry == directory_entry();
1218 if (!State)
1219 return RHS.State->CurrentEntry == directory_entry();
1220 return State->CurrentEntry == RHS.State->CurrentEntry;
1221 }
1222
1223 bool operator!=(const directory_iterator &RHS) const {
1224 return !(*this == RHS);
1225 }
1226};
1227
1228namespace detail {
1229
1230 /// Keeps state for the recursive_directory_iterator.
1231 struct RecDirIterState {
1232 std::stack<directory_iterator, std::vector<directory_iterator>> Stack;
1233 uint16_t Level = 0;
1234 bool HasNoPushRequest = false;
1235 };
1236
1237} // end namespace detail
1238
1239/// recursive_directory_iterator - Same as directory_iterator except for it
1240/// recurses down into child directories.
1241class recursive_directory_iterator {
1242 std::shared_ptr<detail::RecDirIterState> State;
1243 bool Follow;
1244
1245public:
1246 recursive_directory_iterator() = default;
1247 explicit recursive_directory_iterator(const Twine &path, std::error_code &ec,
1248 bool follow_symlinks = true)
1249 : State(std::make_shared<detail::RecDirIterState>()),
1250 Follow(follow_symlinks) {
1251 State->Stack.push(directory_iterator(path, ec, Follow));
1252 if (State->Stack.top() == directory_iterator())
1253 State.reset();
1254 }
1255
1256 // No operator++ because we need error_code.
1257 recursive_directory_iterator &increment(std::error_code &ec) {
1258 const directory_iterator end_itr = {};
1259
1260 if (State->HasNoPushRequest)
1261 State->HasNoPushRequest = false;
1262 else {
1263 file_type type = State->Stack.top()->type();
1264 if (type == file_type::symlink_file && Follow) {
1265 // Resolve the symlink: is it a directory to recurse into?
1266 ErrorOr<basic_file_status> status = State->Stack.top()->status();
1267 if (status)
1268 type = status->type();
1269 // Otherwise broken symlink, and we'll continue.
1270 }
1271 if (type == file_type::directory_file) {
1272 State->Stack.push(directory_iterator(*State->Stack.top(), ec, Follow));
1273 if (State->Stack.top() != end_itr) {
1274 ++State->Level;
1275 return *this;
1276 }
1277 State->Stack.pop();
1278 }
1279 }
1280
1281 while (!State->Stack.empty()
1282 && State->Stack.top().increment(ec) == end_itr) {
1283 State->Stack.pop();
1284 --State->Level;
1285 }
1286
1287 // Check if we are done. If so, create an end iterator.
1288 if (State->Stack.empty())
1289 State.reset();
1290
1291 return *this;
1292 }
1293
1294 const directory_entry &operator*() const { return *State->Stack.top(); }
1295 const directory_entry *operator->() const { return &*State->Stack.top(); }
1296
1297 // observers
1298 /// Gets the current level. Starting path is at level 0.
1299 int level() const { return State->Level; }
1300
1301 /// Returns true if no_push has been called for this directory_entry.
1302 bool no_push_request() const { return State->HasNoPushRequest; }
1303
1304 // modifiers
1305 /// Goes up one level if Level > 0.
1306 void pop() {
1307 assert(State && "Cannot pop an end iterator!");
1308 assert(State->Level > 0 && "Cannot pop an iterator with level < 1");
1309
1310 const directory_iterator end_itr = {};
1311 std::error_code ec;
1312 do {
1313 if (ec)
1314 report_fatal_error("Error incrementing directory iterator.");
1315 State->Stack.pop();
1316 --State->Level;
1317 } while (!State->Stack.empty()
1318 && State->Stack.top().increment(ec) == end_itr);
1319
1320 // Check if we are done. If so, create an end iterator.
1321 if (State->Stack.empty())
1322 State.reset();
1323 }
1324
1325 /// Does not go down into the current directory_entry.
1326 void no_push() { State->HasNoPushRequest = true; }
1327
1328 bool operator==(const recursive_directory_iterator &RHS) const {
1329 return State == RHS.State;
1330 }
1331
1332 bool operator!=(const recursive_directory_iterator &RHS) const {
1333 return !(*this == RHS);
1334 }
1335};
1336
1337/// @}
1338
1339} // end namespace fs
1340} // end namespace sys
1341} // end namespace llvm
1342
1343#endif // LLVM_SUPPORT_FILESYSTEM_H
1344