LLVM 19.0.0git
Path.inc
Go to the documentation of this file.
1//===- llvm/Support/Unix/Path.inc - Unix Path Implementation ----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the Unix specific implementation of the Path API.
10//
11//===----------------------------------------------------------------------===//
12
13//===----------------------------------------------------------------------===//
14//=== WARNING: Implementation here must contain only generic UNIX code that
15//=== is guaranteed to work on *all* UNIX variants.
16//===----------------------------------------------------------------------===//
17
18#include "Unix.h"
19#include <limits.h>
20#include <stdio.h>
21#if HAVE_SYS_STAT_H
22#include <sys/stat.h>
23#endif
24#if HAVE_FCNTL_H
25#include <fcntl.h>
26#endif
27#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
30#ifdef HAVE_SYS_MMAN_H
31#include <sys/mman.h>
32#endif
33
34#include <dirent.h>
35#include <pwd.h>
36#include <sys/file.h>
37
38#ifdef __APPLE__
39#include <copyfile.h>
40#include <mach-o/dyld.h>
41#include <sys/attr.h>
42#if __has_include(<sys/clonefile.h>)
43#include <sys/clonefile.h>
44#endif
45#elif defined(__FreeBSD__)
46#include <osreldate.h>
47#if __FreeBSD_version >= 1300057
48#include <sys/auxv.h>
49#else
50#include <machine/elf.h>
51extern char **environ;
52#endif
53#elif defined(__DragonFly__)
54#include <sys/mount.h>
55#elif defined(__MVS__)
57#include <sys/ps.h>
58#endif
59
60// Both stdio.h and cstdio are included via different paths and
61// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros
62// either.
63#undef ferror
64#undef feof
65
66#if !defined(PATH_MAX)
67// For GNU Hurd
68#if defined(__GNU__)
69#define PATH_MAX 4096
70#elif defined(__MVS__)
71#define PATH_MAX _XOPEN_PATH_MAX
72#endif
73#endif
74
75#include <sys/types.h>
76#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && \
77 !defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(_AIX)
78#include <sys/statvfs.h>
79#define STATVFS statvfs
80#define FSTATVFS fstatvfs
81#define STATVFS_F_FRSIZE(vfs) vfs.f_frsize
82#else
83#if defined(__OpenBSD__) || defined(__FreeBSD__)
84#include <sys/mount.h>
85#include <sys/param.h>
86#elif defined(__linux__)
87#if defined(HAVE_LINUX_MAGIC_H)
88#include <linux/magic.h>
89#else
90#if defined(HAVE_LINUX_NFS_FS_H)
91#include <linux/nfs_fs.h>
92#endif
93#if defined(HAVE_LINUX_SMB_H)
94#include <linux/smb.h>
95#endif
96#endif
97#include <sys/vfs.h>
98#elif defined(_AIX)
99#include <sys/statfs.h>
100
101// <sys/vmount.h> depends on `uint` to be a typedef from <sys/types.h> to
102// `uint_t`; however, <sys/types.h> does not always declare `uint`. We provide
103// the typedef prior to including <sys/vmount.h> to work around this issue.
104typedef uint_t uint;
105#include <sys/vmount.h>
106#else
107#include <sys/mount.h>
108#endif
109#define STATVFS statfs
110#define FSTATVFS fstatfs
111#define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize)
112#endif
113
114#if defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__) || \
115 defined(__MVS__)
116#define STATVFS_F_FLAG(vfs) (vfs).f_flag
117#else
118#define STATVFS_F_FLAG(vfs) (vfs).f_flags
119#endif
120
121using namespace llvm;
122
123namespace llvm {
124namespace sys {
125namespace fs {
126
127const file_t kInvalidFile = -1;
128
129#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \
130 defined(__FreeBSD_kernel__) || defined(__linux__) || defined(__CYGWIN__) || \
131 defined(__DragonFly__) || defined(_AIX) || defined(__GNU__) || \
132 (defined(__sun__) && defined(__svr4__) || defined(__HAIKU__))
133static int test_dir(char ret[PATH_MAX], const char *dir, const char *bin) {
134 struct stat sb;
135 char fullpath[PATH_MAX];
136
137 int chars = snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin);
138 // We cannot write PATH_MAX characters because the string will be terminated
139 // with a null character. Fail if truncation happened.
140 if (chars >= PATH_MAX)
141 return 1;
142 if (!realpath(fullpath, ret))
143 return 1;
144 if (stat(fullpath, &sb) != 0)
145 return 1;
146
147 return 0;
148}
149
150static char *getprogpath(char ret[PATH_MAX], const char *bin) {
151 if (bin == nullptr)
152 return nullptr;
153
154 /* First approach: absolute path. */
155 if (bin[0] == '/') {
156 if (test_dir(ret, "/", bin) == 0)
157 return ret;
158 return nullptr;
159 }
160
161 /* Second approach: relative path. */
162 if (strchr(bin, '/')) {
163 char cwd[PATH_MAX];
164 if (!getcwd(cwd, PATH_MAX))
165 return nullptr;
166 if (test_dir(ret, cwd, bin) == 0)
167 return ret;
168 return nullptr;
169 }
170
171 /* Third approach: $PATH */
172 char *pv;
173 if ((pv = getenv("PATH")) == nullptr)
174 return nullptr;
175 char *s = strdup(pv);
176 if (!s)
177 return nullptr;
178 char *state;
179 for (char *t = strtok_r(s, ":", &state); t != nullptr;
180 t = strtok_r(nullptr, ":", &state)) {
181 if (test_dir(ret, t, bin) == 0) {
182 free(s);
183 return ret;
184 }
185 }
186 free(s);
187 return nullptr;
188}
189#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__
190
191/// GetMainExecutable - Return the path to the main executable, given the
192/// value of argv[0] from program startup.
193std::string getMainExecutable(const char *argv0, void *MainAddr) {
194#if defined(__APPLE__)
195 // On OS X the executable path is saved to the stack by dyld. Reading it
196 // from there is much faster than calling dladdr, especially for large
197 // binaries with symbols.
198 char exe_path[PATH_MAX];
199 uint32_t size = sizeof(exe_path);
200 if (_NSGetExecutablePath(exe_path, &size) == 0) {
201 char link_path[PATH_MAX];
202 if (realpath(exe_path, link_path))
203 return link_path;
204 }
205#elif defined(__FreeBSD__)
206 // On FreeBSD if the exec path specified in ELF auxiliary vectors is
207 // preferred, if available. /proc/curproc/file and the KERN_PROC_PATHNAME
208 // sysctl may not return the desired path if there are multiple hardlinks
209 // to the file.
210 char exe_path[PATH_MAX];
211#if __FreeBSD_version >= 1300057
212 if (elf_aux_info(AT_EXECPATH, exe_path, sizeof(exe_path)) == 0) {
213 char link_path[PATH_MAX];
214 if (realpath(exe_path, link_path))
215 return link_path;
216 }
217#else
218 // elf_aux_info(AT_EXECPATH, ... is not available in all supported versions,
219 // fall back to finding the ELF auxiliary vectors after the process's
220 // environment.
221 char **p = ::environ;
222 while (*p++ != 0)
223 ;
224 // Iterate through auxiliary vectors for AT_EXECPATH.
225 for (Elf_Auxinfo *aux = (Elf_Auxinfo *)p; aux->a_type != AT_NULL; aux++) {
226 if (aux->a_type == AT_EXECPATH) {
227 char link_path[PATH_MAX];
228 if (realpath((char *)aux->a_un.a_ptr, link_path))
229 return link_path;
230 }
231 }
232#endif
233 // Fall back to argv[0] if auxiliary vectors are not available.
234 if (getprogpath(exe_path, argv0) != NULL)
235 return exe_path;
236#elif defined(_AIX) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || \
237 defined(__NetBSD__)
238 const char *curproc = "/proc/curproc/file";
239 char exe_path[PATH_MAX];
240 if (sys::fs::exists(curproc)) {
241 ssize_t len = readlink(curproc, exe_path, sizeof(exe_path));
242 if (len > 0) {
243 // Null terminate the string for realpath. readlink never null
244 // terminates its output.
245 len = std::min(len, ssize_t(sizeof(exe_path) - 1));
246 exe_path[len] = '\0';
247 return exe_path;
248 }
249 }
250 // If we don't have procfs mounted, fall back to argv[0]
251 if (getprogpath(exe_path, argv0) != NULL)
252 return exe_path;
253#elif defined(__linux__) || defined(__CYGWIN__) || defined(__gnu_hurd__)
254 char exe_path[PATH_MAX];
255 const char *aPath = "/proc/self/exe";
256 if (sys::fs::exists(aPath)) {
257 // /proc is not always mounted under Linux (chroot for example).
258 ssize_t len = readlink(aPath, exe_path, sizeof(exe_path));
259 if (len < 0)
260 return "";
261
262 // Null terminate the string for realpath. readlink never null
263 // terminates its output.
264 len = std::min(len, ssize_t(sizeof(exe_path) - 1));
265 exe_path[len] = '\0';
266
267 // On Linux, /proc/self/exe always looks through symlinks. However, on
268 // GNU/Hurd, /proc/self/exe is a symlink to the path that was used to start
269 // the program, and not the eventual binary file. Therefore, call realpath
270 // so this behaves the same on all platforms.
271#if _POSIX_VERSION >= 200112 || defined(__GLIBC__)
272 if (char *real_path = realpath(exe_path, nullptr)) {
273 std::string ret = std::string(real_path);
274 free(real_path);
275 return ret;
276 }
277#else
278 char real_path[PATH_MAX];
279 if (realpath(exe_path, real_path))
280 return std::string(real_path);
281#endif
282 }
283 // Fall back to the classical detection.
284 if (getprogpath(exe_path, argv0))
285 return exe_path;
286#elif defined(__OpenBSD__) || defined(__HAIKU__)
287 char exe_path[PATH_MAX];
288 // argv[0] only
289 if (getprogpath(exe_path, argv0) != NULL)
290 return exe_path;
291#elif defined(__sun__) && defined(__svr4__)
292 char exe_path[PATH_MAX];
293 const char *aPath = "/proc/self/execname";
294 if (sys::fs::exists(aPath)) {
295 int fd = open(aPath, O_RDONLY);
296 if (fd == -1)
297 return "";
298 if (read(fd, exe_path, sizeof(exe_path)) < 0)
299 return "";
300 return exe_path;
301 }
302 // Fall back to the classical detection.
303 if (getprogpath(exe_path, argv0) != NULL)
304 return exe_path;
305#elif defined(__MVS__)
306 int token = 0;
307 W_PSPROC buf;
308 char exe_path[PS_PATHBLEN];
309 pid_t pid = getpid();
310
311 memset(&buf, 0, sizeof(buf));
312 buf.ps_pathptr = exe_path;
313 buf.ps_pathlen = sizeof(exe_path);
314
315 while (true) {
316 if ((token = w_getpsent(token, &buf, sizeof(buf))) <= 0)
317 break;
318 if (buf.ps_pid != pid)
319 continue;
320 char real_path[PATH_MAX];
321 if (realpath(exe_path, real_path))
322 return std::string(real_path);
323 break; // Found entry, but realpath failed.
324 }
325#elif defined(HAVE_DLFCN_H) && defined(HAVE_DLADDR)
326 // Use dladdr to get executable path if available.
327 Dl_info DLInfo;
328 int err = dladdr(MainAddr, &DLInfo);
329 if (err == 0)
330 return "";
331
332 // If the filename is a symlink, we need to resolve and return the location of
333 // the actual executable.
334 char link_path[PATH_MAX];
335 if (realpath(DLInfo.dli_fname, link_path))
336 return link_path;
337#else
338#error GetMainExecutable is not implemented on this host yet.
339#endif
340 return "";
341}
342
345}
346
349}
350
351UniqueID file_status::getUniqueID() const {
352 return UniqueID(fs_st_dev, fs_st_ino);
353}
354
355uint32_t file_status::getLinkCount() const { return fs_st_nlinks; }
356
358 struct STATVFS Vfs;
359 if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs))
360 return errnoAsErrorCode();
361 auto FrSize = STATVFS_F_FRSIZE(Vfs);
362 space_info SpaceInfo;
363 SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize;
364 SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize;
365 SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize;
366 return SpaceInfo;
367}
368
369std::error_code current_path(SmallVectorImpl<char> &result) {
370 result.clear();
371
372 const char *pwd = ::getenv("PWD");
373 llvm::sys::fs::file_status PWDStatus, DotStatus;
374 if (pwd && llvm::sys::path::is_absolute(pwd) &&
375 !llvm::sys::fs::status(pwd, PWDStatus) &&
376 !llvm::sys::fs::status(".", DotStatus) &&
377 PWDStatus.getUniqueID() == DotStatus.getUniqueID()) {
378 result.append(pwd, pwd + strlen(pwd));
379 return std::error_code();
380 }
381
383
384 while (true) {
385 if (::getcwd(result.data(), result.size()) == nullptr) {
386 // See if there was a real error.
387 if (errno != ENOMEM) {
388 result.clear();
389 return errnoAsErrorCode();
390 }
391 // Otherwise there just wasn't enough space.
392 result.resize_for_overwrite(result.capacity() * 2);
393 } else
394 break;
395 }
396
397 result.truncate(strlen(result.data()));
398 return std::error_code();
399}
400
401std::error_code set_current_path(const Twine &path) {
402 SmallString<128> path_storage;
403 StringRef p = path.toNullTerminatedStringRef(path_storage);
404
405 if (::chdir(p.begin()) == -1)
406 return errnoAsErrorCode();
407
408 return std::error_code();
409}
410
411std::error_code create_directory(const Twine &path, bool IgnoreExisting,
412 perms Perms) {
413 SmallString<128> path_storage;
414 StringRef p = path.toNullTerminatedStringRef(path_storage);
415
416 if (::mkdir(p.begin(), Perms) == -1) {
417 if (errno != EEXIST || !IgnoreExisting)
418 return errnoAsErrorCode();
419 }
420
421 return std::error_code();
422}
423
424// Note that we are using symbolic link because hard links are not supported by
425// all filesystems (SMB doesn't).
426std::error_code create_link(const Twine &to, const Twine &from) {
427 // Get arguments.
428 SmallString<128> from_storage;
429 SmallString<128> to_storage;
430 StringRef f = from.toNullTerminatedStringRef(from_storage);
431 StringRef t = to.toNullTerminatedStringRef(to_storage);
432
433 if (::symlink(t.begin(), f.begin()) == -1)
434 return errnoAsErrorCode();
435
436 return std::error_code();
437}
438
439std::error_code create_hard_link(const Twine &to, const Twine &from) {
440 // Get arguments.
441 SmallString<128> from_storage;
442 SmallString<128> to_storage;
443 StringRef f = from.toNullTerminatedStringRef(from_storage);
444 StringRef t = to.toNullTerminatedStringRef(to_storage);
445
446 if (::link(t.begin(), f.begin()) == -1)
447 return errnoAsErrorCode();
448
449 return std::error_code();
450}
451
452std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
453 SmallString<128> path_storage;
454 StringRef p = path.toNullTerminatedStringRef(path_storage);
455
456 struct stat buf;
457 if (lstat(p.begin(), &buf) != 0) {
458 if (errno != ENOENT || !IgnoreNonExisting)
459 return errnoAsErrorCode();
460 return std::error_code();
461 }
462
463 // Note: this check catches strange situations. In all cases, LLVM should
464 // only be involved in the creation and deletion of regular files. This
465 // check ensures that what we're trying to erase is a regular file. It
466 // effectively prevents LLVM from erasing things like /dev/null, any block
467 // special file, or other things that aren't "regular" files.
468 if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode))
470
471 if (::remove(p.begin()) == -1) {
472 if (errno != ENOENT || !IgnoreNonExisting)
473 return errnoAsErrorCode();
474 }
475
476 return std::error_code();
477}
478
479static bool is_local_impl(struct STATVFS &Vfs) {
480#if defined(__linux__) || defined(__GNU__)
481#ifndef NFS_SUPER_MAGIC
482#define NFS_SUPER_MAGIC 0x6969
483#endif
484#ifndef SMB_SUPER_MAGIC
485#define SMB_SUPER_MAGIC 0x517B
486#endif
487#ifndef CIFS_MAGIC_NUMBER
488#define CIFS_MAGIC_NUMBER 0xFF534D42
489#endif
490#ifdef __GNU__
491 switch ((uint32_t)Vfs.__f_type) {
492#else
493 switch ((uint32_t)Vfs.f_type) {
494#endif
495 case NFS_SUPER_MAGIC:
496 case SMB_SUPER_MAGIC:
497 case CIFS_MAGIC_NUMBER:
498 return false;
499 default:
500 return true;
501 }
502#elif defined(__CYGWIN__)
503 // Cygwin doesn't expose this information; would need to use Win32 API.
504 return false;
505#elif defined(__Fuchsia__)
506 // Fuchsia doesn't yet support remote filesystem mounts.
507 return true;
508#elif defined(__EMSCRIPTEN__)
509 // Emscripten doesn't currently support remote filesystem mounts.
510 return true;
511#elif defined(__HAIKU__)
512 // Haiku doesn't expose this information.
513 return false;
514#elif defined(__sun)
515 // statvfs::f_basetype contains a null-terminated FSType name of the mounted
516 // target
517 StringRef fstype(Vfs.f_basetype);
518 // NFS is the only non-local fstype??
519 return !fstype.equals("nfs");
520#elif defined(_AIX)
521 // Call mntctl; try more than twice in case of timing issues with a concurrent
522 // mount.
523 int Ret;
524 size_t BufSize = 2048u;
525 std::unique_ptr<char[]> Buf;
526 int Tries = 3;
527 while (Tries--) {
528 Buf = std::make_unique<char[]>(BufSize);
529 Ret = mntctl(MCTL_QUERY, BufSize, Buf.get());
530 if (Ret != 0)
531 break;
532 BufSize = *reinterpret_cast<unsigned int *>(Buf.get());
533 Buf.reset();
534 }
535
536 if (Ret == -1)
537 // There was an error; "remote" is the conservative answer.
538 return false;
539
540 // Look for the correct vmount entry.
541 char *CurObjPtr = Buf.get();
542 while (Ret--) {
543 struct vmount *Vp = reinterpret_cast<struct vmount *>(CurObjPtr);
544 static_assert(sizeof(Vfs.f_fsid) == sizeof(Vp->vmt_fsid),
545 "fsid length mismatch");
546 if (memcmp(&Vfs.f_fsid, &Vp->vmt_fsid, sizeof Vfs.f_fsid) == 0)
547 return (Vp->vmt_flags & MNT_REMOTE) == 0;
548
549 CurObjPtr += Vp->vmt_length;
550 }
551
552 // vmount entry not found; "remote" is the conservative answer.
553 return false;
554#elif defined(__MVS__)
555 // The file system can have an arbitrary structure on z/OS; must go with the
556 // conservative answer.
557 return false;
558#else
559 return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL);
560#endif
561}
562
563std::error_code is_local(const Twine &Path, bool &Result) {
564 struct STATVFS Vfs;
565 if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs))
566 return errnoAsErrorCode();
567
568 Result = is_local_impl(Vfs);
569 return std::error_code();
570}
571
572std::error_code is_local(int FD, bool &Result) {
573 struct STATVFS Vfs;
574 if (::FSTATVFS(FD, &Vfs))
575 return errnoAsErrorCode();
576
577 Result = is_local_impl(Vfs);
578 return std::error_code();
579}
580
581std::error_code rename(const Twine &from, const Twine &to) {
582 // Get arguments.
583 SmallString<128> from_storage;
584 SmallString<128> to_storage;
585 StringRef f = from.toNullTerminatedStringRef(from_storage);
586 StringRef t = to.toNullTerminatedStringRef(to_storage);
587
588 if (::rename(f.begin(), t.begin()) == -1)
589 return errnoAsErrorCode();
590
591 return std::error_code();
592}
593
594std::error_code resize_file(int FD, uint64_t Size) {
595 // Use ftruncate as a fallback. It may or may not allocate space. At least on
596 // OS X with HFS+ it does.
597 if (::ftruncate(FD, Size) == -1)
598 return errnoAsErrorCode();
599
600 return std::error_code();
601}
602
603static int convertAccessMode(AccessMode Mode) {
604 switch (Mode) {
606 return F_OK;
608 return W_OK;
610 return R_OK | X_OK; // scripts also need R_OK.
611 }
612 llvm_unreachable("invalid enum");
613}
614
615std::error_code access(const Twine &Path, AccessMode Mode) {
616 SmallString<128> PathStorage;
617 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
618
619 if (::access(P.begin(), convertAccessMode(Mode)) == -1)
620 return errnoAsErrorCode();
621
622 if (Mode == AccessMode::Execute) {
623 // Don't say that directories are executable.
624 struct stat buf;
625 if (0 != stat(P.begin(), &buf))
627 if (!S_ISREG(buf.st_mode))
629 }
630
631 return std::error_code();
632}
633
634bool can_execute(const Twine &Path) {
635 return !access(Path, AccessMode::Execute);
636}
637
638bool equivalent(file_status A, file_status B) {
640 return A.fs_st_dev == B.fs_st_dev && A.fs_st_ino == B.fs_st_ino;
641}
642
643std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
644 file_status fsA, fsB;
645 if (std::error_code ec = status(A, fsA))
646 return ec;
647 if (std::error_code ec = status(B, fsB))
648 return ec;
649 result = equivalent(fsA, fsB);
650 return std::error_code();
651}
652
653static void expandTildeExpr(SmallVectorImpl<char> &Path) {
654 StringRef PathStr(Path.begin(), Path.size());
655 if (PathStr.empty() || !PathStr.starts_with("~"))
656 return;
657
658 PathStr = PathStr.drop_front();
659 StringRef Expr =
660 PathStr.take_until([](char c) { return path::is_separator(c); });
661 StringRef Remainder = PathStr.substr(Expr.size() + 1);
662 SmallString<128> Storage;
663 if (Expr.empty()) {
664 // This is just ~/..., resolve it to the current user's home dir.
665 if (!path::home_directory(Storage)) {
666 // For some reason we couldn't get the home directory. Just exit.
667 return;
668 }
669
670 // Overwrite the first character and insert the rest.
671 Path[0] = Storage[0];
672 Path.insert(Path.begin() + 1, Storage.begin() + 1, Storage.end());
673 return;
674 }
675
676 // This is a string of the form ~username/, look up this user's entry in the
677 // password database.
678 std::unique_ptr<char[]> Buf;
679 long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
680 if (BufSize <= 0)
681 BufSize = 16384;
682 Buf = std::make_unique<char[]>(BufSize);
683 struct passwd Pwd;
684 std::string User = Expr.str();
685 struct passwd *Entry = nullptr;
686 getpwnam_r(User.c_str(), &Pwd, Buf.get(), BufSize, &Entry);
687
688 if (!Entry || !Entry->pw_dir) {
689 // Unable to look up the entry, just return back the original path.
690 return;
691 }
692
693 Storage = Remainder;
694 Path.clear();
695 Path.append(Entry->pw_dir, Entry->pw_dir + strlen(Entry->pw_dir));
696 llvm::sys::path::append(Path, Storage);
697}
698
699void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) {
700 dest.clear();
701 if (path.isTriviallyEmpty())
702 return;
703
704 path.toVector(dest);
705 expandTildeExpr(dest);
706}
707
708static file_type typeForMode(mode_t Mode) {
709 if (S_ISDIR(Mode))
711 else if (S_ISREG(Mode))
713 else if (S_ISBLK(Mode))
715 else if (S_ISCHR(Mode))
717 else if (S_ISFIFO(Mode))
719 else if (S_ISSOCK(Mode))
721 else if (S_ISLNK(Mode))
724}
725
726static std::error_code fillStatus(int StatRet, const struct stat &Status,
727 file_status &Result) {
728 if (StatRet != 0) {
729 std::error_code EC = errnoAsErrorCode();
731 Result = file_status(file_type::file_not_found);
732 else
733 Result = file_status(file_type::status_error);
734 return EC;
735 }
736
737 uint32_t atime_nsec, mtime_nsec;
738#if defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
739 atime_nsec = Status.st_atimespec.tv_nsec;
740 mtime_nsec = Status.st_mtimespec.tv_nsec;
741#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
742 atime_nsec = Status.st_atim.tv_nsec;
743 mtime_nsec = Status.st_mtim.tv_nsec;
744#else
745 atime_nsec = mtime_nsec = 0;
746#endif
747
748 perms Perms = static_cast<perms>(Status.st_mode) & all_perms;
749 Result = file_status(typeForMode(Status.st_mode), Perms, Status.st_dev,
750 Status.st_nlink, Status.st_ino, Status.st_atime,
751 atime_nsec, Status.st_mtime, mtime_nsec, Status.st_uid,
752 Status.st_gid, Status.st_size);
753
754 return std::error_code();
755}
756
757std::error_code status(const Twine &Path, file_status &Result, bool Follow) {
758 SmallString<128> PathStorage;
759 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
760
761 struct stat Status;
762 int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status);
763 return fillStatus(StatRet, Status, Result);
764}
765
766std::error_code status(int FD, file_status &Result) {
767 struct stat Status;
768 int StatRet = ::fstat(FD, &Status);
769 return fillStatus(StatRet, Status, Result);
770}
771
772unsigned getUmask() {
773 // Chose arbitary new mask and reset the umask to the old mask.
774 // umask(2) never fails so ignore the return of the second call.
775 unsigned Mask = ::umask(0);
776 (void)::umask(Mask);
777 return Mask;
778}
779
780std::error_code setPermissions(const Twine &Path, perms Permissions) {
781 SmallString<128> PathStorage;
782 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
783
784 if (::chmod(P.begin(), Permissions))
785 return errnoAsErrorCode();
786 return std::error_code();
787}
788
789std::error_code setPermissions(int FD, perms Permissions) {
790 if (::fchmod(FD, Permissions))
791 return errnoAsErrorCode();
792 return std::error_code();
793}
794
795std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
796 TimePoint<> ModificationTime) {
797#if defined(HAVE_FUTIMENS)
798 timespec Times[2];
799 Times[0] = sys::toTimeSpec(AccessTime);
800 Times[1] = sys::toTimeSpec(ModificationTime);
801 if (::futimens(FD, Times))
802 return errnoAsErrorCode();
803 return std::error_code();
804#elif defined(HAVE_FUTIMES)
805 timeval Times[2];
806 Times[0] = sys::toTimeVal(
807 std::chrono::time_point_cast<std::chrono::microseconds>(AccessTime));
808 Times[1] =
809 sys::toTimeVal(std::chrono::time_point_cast<std::chrono::microseconds>(
810 ModificationTime));
811 if (::futimes(FD, Times))
812 return errnoAsErrorCode();
813 return std::error_code();
814#elif defined(__MVS__)
815 attrib_t Attr;
816 memset(&Attr, 0, sizeof(Attr));
817 Attr.att_atimechg = 1;
818 Attr.att_atime = sys::toTimeT(AccessTime);
819 Attr.att_mtimechg = 1;
820 Attr.att_mtime = sys::toTimeT(ModificationTime);
821 if (::__fchattr(FD, &Attr, sizeof(Attr)) != 0)
822 return errnoAsErrorCode();
823 return std::error_code();
824#else
825#warning Missing futimes() and futimens()
827#endif
828}
829
830std::error_code mapped_file_region::init(int FD, uint64_t Offset,
831 mapmode Mode) {
832 assert(Size != 0);
833
834 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE;
835 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE);
836#if defined(MAP_NORESERVE)
837 flags |= MAP_NORESERVE;
838#endif
839#if defined(__APPLE__)
840 //----------------------------------------------------------------------
841 // Newer versions of MacOSX have a flag that will allow us to read from
842 // binaries whose code signature is invalid without crashing by using
843 // the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media
844 // is mapped we can avoid crashing and return zeroes to any pages we try
845 // to read if the media becomes unavailable by using the
846 // MAP_RESILIENT_MEDIA flag. These flags are only usable when mapping
847 // with PROT_READ, so take care not to specify them otherwise.
848 //----------------------------------------------------------------------
849 if (Mode == readonly) {
850#if defined(MAP_RESILIENT_CODESIGN)
851 flags |= MAP_RESILIENT_CODESIGN;
852#endif
853#if defined(MAP_RESILIENT_MEDIA)
854 flags |= MAP_RESILIENT_MEDIA;
855#endif
856 }
857#endif // #if defined (__APPLE__)
858
859 Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset);
860 if (Mapping == MAP_FAILED)
861 return errnoAsErrorCode();
862 return std::error_code();
863}
864
865mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length,
866 uint64_t offset, std::error_code &ec)
867 : Size(length), Mode(mode) {
868 (void)Mode;
869 ec = init(fd, offset, mode);
870 if (ec)
871 copyFrom(mapped_file_region());
872}
873
874void mapped_file_region::unmapImpl() {
875 if (Mapping)
876 ::munmap(Mapping, Size);
877}
878
879void mapped_file_region::dontNeedImpl() {
880 assert(Mode == mapped_file_region::readonly);
881 if (!Mapping)
882 return;
883#if defined(__MVS__) || defined(_AIX)
884 // If we don't have madvise, or it isn't beneficial, treat this as a no-op.
885#elif defined(POSIX_MADV_DONTNEED)
886 ::posix_madvise(Mapping, Size, POSIX_MADV_DONTNEED);
887#else
888 ::madvise(Mapping, Size, MADV_DONTNEED);
889#endif
890}
891
892int mapped_file_region::alignment() { return Process::getPageSizeEstimate(); }
893
894std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
895 StringRef path,
896 bool follow_symlinks) {
897 SmallString<128> path_null(path);
898 DIR *directory = ::opendir(path_null.c_str());
899 if (!directory)
900 return errnoAsErrorCode();
901
902 it.IterationHandle = reinterpret_cast<intptr_t>(directory);
903 // Add something for replace_filename to replace.
904 path::append(path_null, ".");
905 it.CurrentEntry = directory_entry(path_null.str(), follow_symlinks);
907}
908
909std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
910 if (it.IterationHandle)
911 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle));
912 it.IterationHandle = 0;
913 it.CurrentEntry = directory_entry();
914 return std::error_code();
915}
916
917static file_type direntType(dirent *Entry) {
918 // Most platforms provide the file type in the dirent: Linux/BSD/Mac.
919 // The DTTOIF macro lets us reuse our status -> type conversion.
920 // Note that while glibc provides a macro to see if this is supported,
921 // _DIRENT_HAVE_D_TYPE, it's not defined on BSD/Mac, so we test for the
922 // d_type-to-mode_t conversion macro instead.
923#if defined(DTTOIF)
924 return typeForMode(DTTOIF(Entry->d_type));
925#else
926 // Other platforms such as Solaris require a stat() to get the type.
927 return file_type::type_unknown;
928#endif
929}
930
931std::error_code detail::directory_iterator_increment(detail::DirIterState &It) {
932 errno = 0;
933 dirent *CurDir = ::readdir(reinterpret_cast<DIR *>(It.IterationHandle));
934 if (CurDir == nullptr && errno != 0) {
935 return errnoAsErrorCode();
936 } else if (CurDir != nullptr) {
937 StringRef Name(CurDir->d_name);
938 if ((Name.size() == 1 && Name[0] == '.') ||
939 (Name.size() == 2 && Name[0] == '.' && Name[1] == '.'))
941 It.CurrentEntry.replace_filename(Name, direntType(CurDir));
942 } else
944
945 return std::error_code();
946}
947
948ErrorOr<basic_file_status> directory_entry::status() const {
949 file_status s;
950 if (auto EC = fs::status(Path, s, FollowSymlinks))
951 return EC;
952 return s;
953}
954
955//
956// FreeBSD optionally provides /proc/self/fd, but it is incompatible with
957// Linux. The thing to use is realpath.
958//
959#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
960#define TRY_PROC_SELF_FD
961#endif
962
963#if !defined(F_GETPATH) && defined(TRY_PROC_SELF_FD)
964static bool hasProcSelfFD() {
965 // If we have a /proc filesystem mounted, we can quickly establish the
966 // real name of the file with readlink
967 static const bool Result = (::access("/proc/self/fd", R_OK) == 0);
968 return Result;
969}
970#endif
971
972static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
973 FileAccess Access) {
974 int Result = 0;
975 if (Access == FA_Read)
976 Result |= O_RDONLY;
977 else if (Access == FA_Write)
978 Result |= O_WRONLY;
979 else if (Access == (FA_Read | FA_Write))
980 Result |= O_RDWR;
981
982 // This is for compatibility with old code that assumed OF_Append implied
983 // would open an existing file. See Windows/Path.inc for a longer comment.
984 if (Flags & OF_Append)
985 Disp = CD_OpenAlways;
986
987 if (Disp == CD_CreateNew) {
988 Result |= O_CREAT; // Create if it doesn't exist.
989 Result |= O_EXCL; // Fail if it does.
990 } else if (Disp == CD_CreateAlways) {
991 Result |= O_CREAT; // Create if it doesn't exist.
992 Result |= O_TRUNC; // Truncate if it does.
993 } else if (Disp == CD_OpenAlways) {
994 Result |= O_CREAT; // Create if it doesn't exist.
995 } else if (Disp == CD_OpenExisting) {
996 // Nothing special, just don't add O_CREAT and we get these semantics.
997 }
998
999// Using append mode with z/OS UTF-8 auto-conversion results in EINVAL when
1000// calling write(). Instead we need to use lseek() to set offset to EOF after
1001// open().
1002#ifndef __MVS__
1003 if (Flags & OF_Append)
1004 Result |= O_APPEND;
1005#endif
1006
1007#ifdef O_CLOEXEC
1008 if (!(Flags & OF_ChildInherit))
1009 Result |= O_CLOEXEC;
1010#endif
1011
1012 return Result;
1013}
1014
1015std::error_code openFile(const Twine &Name, int &ResultFD,
1016 CreationDisposition Disp, FileAccess Access,
1017 OpenFlags Flags, unsigned Mode) {
1018 int OpenFlags = nativeOpenFlags(Disp, Flags, Access);
1019
1020 SmallString<128> Storage;
1021 StringRef P = Name.toNullTerminatedStringRef(Storage);
1022 // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal
1023 // when open is overloaded, such as in Bionic.
1024 auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); };
1025 if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0)
1026 return errnoAsErrorCode();
1027#ifndef O_CLOEXEC
1028 if (!(Flags & OF_ChildInherit)) {
1029 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
1030 (void)r;
1031 assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed");
1032 }
1033#endif
1034
1035#ifdef __MVS__
1036 /* Reason about auto-conversion and file tags. Setting the file tag only
1037 * applies if file is opened in write mode:
1038 *
1039 * Text file:
1040 * File exists File created
1041 * CD_CreateNew n/a conv: on
1042 * tag: set 1047
1043 * CD_CreateAlways conv: auto conv: on
1044 * tag: auto 1047 tag: set 1047
1045 * CD_OpenAlways conv: auto conv: on
1046 * tag: auto 1047 tag: set 1047
1047 * CD_OpenExisting conv: auto n/a
1048 * tag: unchanged
1049 *
1050 * Binary file:
1051 * File exists File created
1052 * CD_CreateNew n/a conv: off
1053 * tag: set binary
1054 * CD_CreateAlways conv: off conv: off
1055 * tag: auto binary tag: set binary
1056 * CD_OpenAlways conv: off conv: off
1057 * tag: auto binary tag: set binary
1058 * CD_OpenExisting conv: off n/a
1059 * tag: unchanged
1060 *
1061 * Actions:
1062 * conv: off -> auto-conversion is turned off
1063 * conv: on -> auto-conversion is turned on
1064 * conv: auto -> auto-conversion is turned on if the file is untagged
1065 * tag: set 1047 -> set the file tag to text encoded in 1047
1066 * tag: set binary -> set the file tag to binary
1067 * tag: auto 1047 -> set file tag to 1047 if not set
1068 * tag: auto binary -> set file tag to binary if not set
1069 * tag: unchanged -> do not care about the file tag
1070 *
1071 * It is not possible to distinguish between the cases "file exists" and
1072 * "file created". In the latter case, the file tag is not set and the file
1073 * size is zero. The decision table boils down to:
1074 *
1075 * the file tag is set if
1076 * - the file is opened for writing
1077 * - the create disposition is not equal to CD_OpenExisting
1078 * - the file tag is not set
1079 * - the file size is zero
1080 *
1081 * This only applies if the file is a regular file. E.g. enabling
1082 * auto-conversion for reading from /dev/null results in error EINVAL when
1083 * calling read().
1084 *
1085 * Using append mode with z/OS UTF-8 auto-conversion results in EINVAL when
1086 * calling write(). Instead we need to use lseek() to set offset to EOF after
1087 * open().
1088 */
1089 if ((Flags & OF_Append) && lseek(ResultFD, 0, SEEK_END) == -1)
1090 return errnoAsErrorCode();
1091 struct stat Stat;
1092 if (fstat(ResultFD, &Stat) == -1)
1093 return errnoAsErrorCode();
1094 if (S_ISREG(Stat.st_mode)) {
1095 bool DoSetTag = (Access & FA_Write) && (Disp != CD_OpenExisting) &&
1096 !Stat.st_tag.ft_txtflag && !Stat.st_tag.ft_ccsid &&
1097 Stat.st_size == 0;
1098 if (Flags & OF_Text) {
1099 if (auto EC = llvm::enableAutoConversion(ResultFD))
1100 return EC;
1101 if (DoSetTag) {
1102 if (auto EC = llvm::setFileTag(ResultFD, CCSID_IBM_1047, true))
1103 return EC;
1104 }
1105 } else {
1106 if (auto EC = llvm::disableAutoConversion(ResultFD))
1107 return EC;
1108 if (DoSetTag) {
1109 if (auto EC = llvm::setFileTag(ResultFD, FT_BINARY, false))
1110 return EC;
1111 }
1112 }
1113 }
1114#endif
1115
1116 return std::error_code();
1117}
1118
1119Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp,
1120 FileAccess Access, OpenFlags Flags,
1121 unsigned Mode) {
1122
1123 int FD;
1124 std::error_code EC = openFile(Name, FD, Disp, Access, Flags, Mode);
1125 if (EC)
1126 return errorCodeToError(EC);
1127 return FD;
1128}
1129
1130std::error_code openFileForRead(const Twine &Name, int &ResultFD,
1131 OpenFlags Flags,
1132 SmallVectorImpl<char> *RealPath) {
1133 std::error_code EC =
1134 openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666);
1135 if (EC)
1136 return EC;
1137
1138 // Attempt to get the real name of the file, if the user asked
1139 if (!RealPath)
1140 return std::error_code();
1141 RealPath->clear();
1142#if defined(F_GETPATH)
1143 // When F_GETPATH is availble, it is the quickest way to get
1144 // the real path name.
1145 char Buffer[PATH_MAX];
1146 if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1)
1147 RealPath->append(Buffer, Buffer + strlen(Buffer));
1148#else
1149 char Buffer[PATH_MAX];
1150#if defined(TRY_PROC_SELF_FD)
1151 if (hasProcSelfFD()) {
1152 char ProcPath[64];
1153 snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD);
1154 ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer));
1155 if (CharCount > 0)
1156 RealPath->append(Buffer, Buffer + CharCount);
1157 } else {
1158#endif
1159 SmallString<128> Storage;
1160 StringRef P = Name.toNullTerminatedStringRef(Storage);
1161
1162 // Use ::realpath to get the real path name
1163 if (::realpath(P.begin(), Buffer) != nullptr)
1164 RealPath->append(Buffer, Buffer + strlen(Buffer));
1165#if defined(TRY_PROC_SELF_FD)
1166 }
1167#endif
1168#endif
1169 return std::error_code();
1170}
1171
1172Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags,
1173 SmallVectorImpl<char> *RealPath) {
1174 file_t ResultFD;
1175 std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath);
1176 if (EC)
1177 return errorCodeToError(EC);
1178 return ResultFD;
1179}
1180
1181file_t getStdinHandle() { return 0; }
1182file_t getStdoutHandle() { return 1; }
1183file_t getStderrHandle() { return 2; }
1184
1186#if defined(__APPLE__)
1187 size_t Size = std::min<size_t>(Buf.size(), INT32_MAX);
1188#else
1189 size_t Size = Buf.size();
1190#endif
1191 ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size);
1192 if (ssize_t(NumRead) == -1)
1194 return NumRead;
1195}
1196
1198 uint64_t Offset) {
1199#if defined(__APPLE__)
1200 size_t Size = std::min<size_t>(Buf.size(), INT32_MAX);
1201#else
1202 size_t Size = Buf.size();
1203#endif
1204#ifdef HAVE_PREAD
1205 ssize_t NumRead =
1206 sys::RetryAfterSignal(-1, ::pread, FD, Buf.data(), Size, Offset);
1207#else
1208 if (lseek(FD, Offset, SEEK_SET) == -1)
1210 ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size);
1211#endif
1212 if (NumRead == -1)
1214 return NumRead;
1215}
1216
1217std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout) {
1218 auto Start = std::chrono::steady_clock::now();
1219 auto End = Start + Timeout;
1220 do {
1221 struct flock Lock;
1222 memset(&Lock, 0, sizeof(Lock));
1223 Lock.l_type = F_WRLCK;
1224 Lock.l_whence = SEEK_SET;
1225 Lock.l_start = 0;
1226 Lock.l_len = 0;
1227 if (::fcntl(FD, F_SETLK, &Lock) != -1)
1228 return std::error_code();
1229 int Error = errno;
1230 if (Error != EACCES && Error != EAGAIN)
1231 return std::error_code(Error, std::generic_category());
1232 usleep(1000);
1233 } while (std::chrono::steady_clock::now() < End);
1234 return make_error_code(errc::no_lock_available);
1235}
1236
1237std::error_code lockFile(int FD) {
1238 struct flock Lock;
1239 memset(&Lock, 0, sizeof(Lock));
1240 Lock.l_type = F_WRLCK;
1241 Lock.l_whence = SEEK_SET;
1242 Lock.l_start = 0;
1243 Lock.l_len = 0;
1244 if (::fcntl(FD, F_SETLKW, &Lock) != -1)
1245 return std::error_code();
1246 return errnoAsErrorCode();
1247}
1248
1249std::error_code unlockFile(int FD) {
1250 struct flock Lock;
1251 Lock.l_type = F_UNLCK;
1252 Lock.l_whence = SEEK_SET;
1253 Lock.l_start = 0;
1254 Lock.l_len = 0;
1255 if (::fcntl(FD, F_SETLK, &Lock) != -1)
1256 return std::error_code();
1257 return errnoAsErrorCode();
1258}
1259
1260std::error_code closeFile(file_t &F) {
1261 file_t TmpF = F;
1262 F = kInvalidFile;
1263 return Process::SafelyCloseFileDescriptor(TmpF);
1264}
1265
1266template <typename T>
1267static std::error_code remove_directories_impl(const T &Entry,
1268 bool IgnoreErrors) {
1269 std::error_code EC;
1270 directory_iterator Begin(Entry, EC, false);
1271 directory_iterator End;
1272 while (Begin != End) {
1273 auto &Item = *Begin;
1274 ErrorOr<basic_file_status> st = Item.status();
1275 if (st) {
1276 if (is_directory(*st)) {
1277 EC = remove_directories_impl(Item, IgnoreErrors);
1278 if (EC && !IgnoreErrors)
1279 return EC;
1280 }
1281
1282 EC = fs::remove(Item.path(), true);
1283 if (EC && !IgnoreErrors)
1284 return EC;
1285 } else if (!IgnoreErrors) {
1286 return st.getError();
1287 }
1288
1289 Begin.increment(EC);
1290 if (EC && !IgnoreErrors)
1291 return EC;
1292 }
1293 return std::error_code();
1294}
1295
1296std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
1297 auto EC = remove_directories_impl(path, IgnoreErrors);
1298 if (EC && !IgnoreErrors)
1299 return EC;
1300 EC = fs::remove(path, true);
1301 if (EC && !IgnoreErrors)
1302 return EC;
1303 return std::error_code();
1304}
1305
1306std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
1307 bool expand_tilde) {
1308 dest.clear();
1309 if (path.isTriviallyEmpty())
1310 return std::error_code();
1311
1312 if (expand_tilde) {
1313 SmallString<128> Storage;
1314 path.toVector(Storage);
1315 expandTildeExpr(Storage);
1316 return real_path(Storage, dest, false);
1317 }
1318
1319 SmallString<128> Storage;
1320 StringRef P = path.toNullTerminatedStringRef(Storage);
1321 char Buffer[PATH_MAX];
1322 if (::realpath(P.begin(), Buffer) == nullptr)
1323 return errnoAsErrorCode();
1324 dest.append(Buffer, Buffer + strlen(Buffer));
1325 return std::error_code();
1326}
1327
1328std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group) {
1329 auto FChown = [&]() { return ::fchown(FD, Owner, Group); };
1330 // Retry if fchown call fails due to interruption.
1331 if ((sys::RetryAfterSignal(-1, FChown)) < 0)
1332 return errnoAsErrorCode();
1333 return std::error_code();
1334}
1335
1336} // end namespace fs
1337
1338namespace path {
1339
1341 std::unique_ptr<char[]> Buf;
1342 char *RequestedDir = getenv("HOME");
1343 if (!RequestedDir) {
1344 long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
1345 if (BufSize <= 0)
1346 BufSize = 16384;
1347 Buf = std::make_unique<char[]>(BufSize);
1348 struct passwd Pwd;
1349 struct passwd *pw = nullptr;
1350 getpwuid_r(getuid(), &Pwd, Buf.get(), BufSize, &pw);
1351 if (pw && pw->pw_dir)
1352 RequestedDir = pw->pw_dir;
1353 }
1354 if (!RequestedDir)
1355 return false;
1356
1357 result.clear();
1358 result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1359 return true;
1360}
1361
1362static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) {
1363#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR)
1364 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR.
1365 // macros defined in <unistd.h> on darwin >= 9
1366 int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR : _CS_DARWIN_USER_CACHE_DIR;
1367 size_t ConfLen = confstr(ConfName, nullptr, 0);
1368 if (ConfLen > 0) {
1369 do {
1370 Result.resize(ConfLen);
1371 ConfLen = confstr(ConfName, Result.data(), Result.size());
1372 } while (ConfLen > 0 && ConfLen != Result.size());
1373
1374 if (ConfLen > 0) {
1375 assert(Result.back() == 0);
1376 Result.pop_back();
1377 return true;
1378 }
1379
1380 Result.clear();
1381 }
1382#endif
1383 return false;
1384}
1385
1387#ifdef __APPLE__
1388 // Mac: ~/Library/Preferences/
1389 if (home_directory(result)) {
1390 append(result, "Library", "Preferences");
1391 return true;
1392 }
1393#else
1394 // XDG_CONFIG_HOME as defined in the XDG Base Directory Specification:
1395 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
1396 if (const char *RequestedDir = getenv("XDG_CONFIG_HOME")) {
1397 result.clear();
1398 result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1399 return true;
1400 }
1401#endif
1402 // Fallback: ~/.config
1403 if (!home_directory(result)) {
1404 return false;
1405 }
1406 append(result, ".config");
1407 return true;
1408}
1409
1411#ifdef __APPLE__
1412 if (getDarwinConfDir(false /*tempDir*/, result)) {
1413 return true;
1414 }
1415#else
1416 // XDG_CACHE_HOME as defined in the XDG Base Directory Specification:
1417 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
1418 if (const char *RequestedDir = getenv("XDG_CACHE_HOME")) {
1419 result.clear();
1420 result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1421 return true;
1422 }
1423#endif
1424 if (!home_directory(result)) {
1425 return false;
1426 }
1427 append(result, ".cache");
1428 return true;
1429}
1430
1431static const char *getEnvTempDir() {
1432 // Check whether the temporary directory is specified by an environment
1433 // variable.
1434 const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
1435 for (const char *Env : EnvironmentVariables) {
1436 if (const char *Dir = std::getenv(Env))
1437 return Dir;
1438 }
1439
1440 return nullptr;
1441}
1442
1443static const char *getDefaultTempDir(bool ErasedOnReboot) {
1444#ifdef P_tmpdir
1445 if ((bool)P_tmpdir)
1446 return P_tmpdir;
1447#endif
1448
1449 if (ErasedOnReboot)
1450 return "/tmp";
1451 return "/var/tmp";
1452}
1453
1454void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
1455 Result.clear();
1456
1457 if (ErasedOnReboot) {
1458 // There is no env variable for the cache directory.
1459 if (const char *RequestedDir = getEnvTempDir()) {
1460 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1461 return;
1462 }
1463 }
1464
1465 if (getDarwinConfDir(ErasedOnReboot, Result))
1466 return;
1467
1468 const char *RequestedDir = getDefaultTempDir(ErasedOnReboot);
1469 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1470}
1471
1472} // end namespace path
1473
1474namespace fs {
1475
1476#ifdef __APPLE__
1477/// This implementation tries to perform an APFS CoW clone of the file,
1478/// which can be much faster and uses less space.
1479/// Unfortunately fcopyfile(3) does not support COPYFILE_CLONE, so the
1480/// file descriptor variant of this function still uses the default
1481/// implementation.
1482std::error_code copy_file(const Twine &From, const Twine &To) {
1483 std::string FromS = From.str();
1484 std::string ToS = To.str();
1485#if __has_builtin(__builtin_available)
1486 if (__builtin_available(macos 10.12, *)) {
1487 // Optimistically try to use clonefile() and handle errors, rather than
1488 // calling stat() to see if it'll work.
1489 //
1490 // Note: It's okay if From is a symlink. In contrast to the behaviour of
1491 // copyfile() with COPYFILE_CLONE, clonefile() clones targets (not the
1492 // symlink itself) unless the flag CLONE_NOFOLLOW is passed.
1493 if (!clonefile(FromS.c_str(), ToS.c_str(), 0))
1494 return std::error_code();
1495
1496 auto Errno = errno;
1497 switch (Errno) {
1498 case EEXIST: // To already exists.
1499 case ENOTSUP: // Device does not support cloning.
1500 case EXDEV: // From and To are on different devices.
1501 break;
1502 default:
1503 // Anything else will also break copyfile().
1504 return std::error_code(Errno, std::generic_category());
1505 }
1506
1507 // TODO: For EEXIST, profile calling fs::generateUniqueName() and
1508 // clonefile() in a retry loop (then rename() on success) before falling
1509 // back to copyfile(). Depending on the size of the file this could be
1510 // cheaper.
1511 }
1512#endif
1513 if (!copyfile(FromS.c_str(), ToS.c_str(), /*State=*/NULL, COPYFILE_DATA))
1514 return std::error_code();
1515 return errnoAsErrorCode();
1516}
1517#endif // __APPLE__
1518
1519} // end namespace fs
1520
1521} // end namespace sys
1522} // end namespace llvm
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
std::string Name
uint64_t Size
bool End
Definition: ELF_riscv.cpp:480
uint64_t Offset
Definition: ELF_riscv.cpp:478
amode Optimize addressing mode
std::unique_ptr< MemoryBuffer > openFile(const Twine &Path)
Definition: LibDriver.cpp:97
#define F(x, y, z)
Definition: MD5.cpp:55
Merge contiguous icmps into a memcmp
Definition: MergeICmps.cpp:911
#define P(N)
static cl::opt< RegAllocEvictionAdvisorAnalysis::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development, "development", "for training")))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
#define PATH_MAX
Definition: Utils.h:23
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
Represents either an error or a value T.
Definition: ErrorOr.h:56
std::error_code getError() const
Definition: ErrorOr.h:152
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
Tagged union holding either a T or a Error.
Definition: Error.h:474
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:307
T * data() const
Definition: ArrayRef.h:354
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
size_t capacity() const
Definition: SmallVector.h:92
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
Definition: SmallVector.h:654
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:696
void truncate(size_type N)
Like resize, but requires that N is less than size().
Definition: SmallVector.h:657
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:299
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:222
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:567
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
iterator begin() const
Definition: StringRef.h:111
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
StringRef take_until(function_ref< bool(char)> F) const
Return the longest prefix of 'this' such that no character in the prefix satisfies the given predicat...
Definition: StringRef.h:599
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
StringRef toNullTerminatedStringRef(SmallVectorImpl< char > &Out) const
This returns the twine as a single null terminated StringRef if it can be represented as such.
Definition: Twine.cpp:37
bool isTriviallyEmpty() const
Check if this twine is trivially empty; a false return value does not necessarily mean the twine is e...
Definition: Twine.h:429
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
Definition: Twine.cpp:32
TimePoint getLastAccessedTime() const
The file access time as reported from the underlying file system.
TimePoint getLastModificationTime() const
The file modification time as reported from the underlying file system.
Represents the result of a call to sys::fs::status().
Definition: FileSystem.h:226
uint32_t getLinkCount() const
UniqueID getUniqueID() const
@ readonly
May only access map via const_data as read only.
Definition: FileSystem.h:1270
@ readwrite
May access map via data and modify it. Written to path.
Definition: FileSystem.h:1271
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:121
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition: Endian.h:58
std::error_code directory_iterator_destruct(DirIterState &)
std::error_code directory_iterator_increment(DirIterState &)
std::error_code unlockFile(int FD)
Unlock the file.
std::string getMainExecutable(const char *argv0, void *MainExecAddr)
Return the path to the main executable, given the value of argv[0] from program startup and the addre...
std::error_code remove_directories(const Twine &path, bool IgnoreErrors=true)
Recursively delete a directory.
std::error_code create_link(const Twine &to, const Twine &from)
Create a link from from to to.
bool equivalent(file_status A, file_status B)
Do file_status's represent the same thing?
const file_t kInvalidFile
std::error_code real_path(const Twine &path, SmallVectorImpl< char > &output, bool expand_tilde=false)
Collapse all .
std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout=std::chrono::milliseconds(0))
Try to locks the file during the specified time.
Expected< size_t > readNativeFile(file_t FileHandle, MutableArrayRef< char > Buf)
Reads Buf.size() bytes from FileHandle into Buf.
std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, TimePoint<> ModificationTime)
Set the file modification and access time.
std::error_code closeFile(file_t &F)
Close the file object.
file_t getStdoutHandle()
Return an open handle to standard out.
std::error_code rename(const Twine &from, const Twine &to)
Rename from to to.
std::error_code openFileForRead(const Twine &Name, int &ResultFD, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
void expand_tilde(const Twine &path, SmallVectorImpl< char > &output)
Expands ~ expressions to the user's home directory.
Expected< size_t > readNativeFileSlice(file_t FileHandle, MutableArrayRef< char > Buf, uint64_t Offset)
Reads Buf.size() bytes from FileHandle at offset Offset into Buf.
std::error_code access(const Twine &Path, AccessMode Mode)
Can the file be accessed?
std::error_code status(const Twine &path, file_status &result, bool follow=true)
Get file status as if by POSIX stat().
bool exists(const basic_file_status &status)
Does file exist?
Definition: Path.cpp:1078
file_type
An enumeration for the file system's view of the type.
Definition: FileSystem.h:66
std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group)
Change ownership of a file.
std::error_code create_hard_link(const Twine &to, const Twine &from)
Create a hard link from from to to, or return an error.
std::error_code resize_file(int FD, uint64_t Size)
Resize path to size.
std::error_code create_directory(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create the directory in path.
std::error_code lockFile(int FD)
Lock the file.
std::error_code remove(const Twine &path, bool IgnoreNonExisting=true)
Remove path.
@ CD_OpenAlways
CD_OpenAlways - When opening a file:
Definition: FileSystem.h:746
std::error_code set_current_path(const Twine &path)
Set the current path.
Expected< file_t > openNativeFile(const Twine &Name, CreationDisposition Disp, FileAccess Access, OpenFlags Flags, unsigned Mode=0666)
Opens a file with the specified creation disposition, access mode, and flags and returns a platform-s...
ErrorOr< space_info > disk_space(const Twine &Path)
Get disk space usage information.
file_t getStderrHandle()
Return an open handle to standard error.
bool status_known(const basic_file_status &s)
Is status available?
Definition: Path.cpp:1082
std::error_code is_local(const Twine &path, bool &result)
Is the file mounted on a local filesystem?
std::error_code copy_file(const Twine &From, const Twine &To)
Copy the contents of From to To.
Definition: Path.cpp:1017
bool can_execute(const Twine &Path)
Can we execute this file?
unsigned getUmask()
Get file creation mode mask of the process.
Expected< file_t > openNativeFileForRead(const Twine &Name, OpenFlags Flags=OF_None, SmallVectorImpl< char > *RealPath=nullptr)
Opens the file with the given name in a read-only mode, returning its open file descriptor.
std::error_code current_path(SmallVectorImpl< char > &result)
Get the current path.
std::error_code setPermissions(const Twine &Path, perms Permissions)
Set file permissions.
bool is_directory(const basic_file_status &status)
Does status represent a directory?
Definition: Path.cpp:1093
file_t getStdinHandle()
Return an open handle to standard in.
bool user_config_directory(SmallVectorImpl< char > &result)
Get the directory where packages should read user-specific configurations.
bool home_directory(SmallVectorImpl< char > &result)
Get the user's home directory.
bool cache_directory(SmallVectorImpl< char > &result)
Get the directory where installed packages should put their machine-local cache, e....
void system_temp_directory(bool erasedOnReboot, SmallVectorImpl< char > &result)
Get the typical temporary directory for the system, e.g., "/var/tmp" or "C:/TEMP".
bool is_absolute(const Twine &path, Style style=Style::native)
Is path absolute?
Definition: Path.cpp:672
void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition: Path.cpp:457
bool is_separator(char value, Style style=Style::native)
Check whether the given char is a path separator on the host OS.
Definition: Path.cpp:602
std::chrono::time_point< std::chrono::system_clock, D > TimePoint
A time point on the system clock.
Definition: Chrono.h:34
TimePoint< std::chrono::seconds > toTimePoint(std::time_t T)
Convert a std::time_t to a TimePoint.
Definition: Chrono.h:65
struct timespec toTimeSpec(TimePoint<> TP)
Convert a time point to struct timespec.
Definition: Unix.h:87
struct timeval toTimeVal(TimePoint< std::chrono::microseconds > TP)
Convert a time point to struct timeval.
Definition: Unix.h:97
std::time_t toTimeT(TimePoint<> TP)
Convert a TimePoint to std::time_t.
Definition: Chrono.h:50
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:456
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1689
std::error_code make_error_code(BitcodeError E)
@ no_such_file_or_directory
@ operation_not_permitted
@ function_not_supported
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Definition: Error.cpp:103
std::error_code errnoAsErrorCode()
Helper to get errno as an std::error_code.
Definition: Error.h:1193