LLVM 17.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(__minix) || defined(__FreeBSD_kernel__) || defined(__linux__) || \
131 defined(__CYGWIN__) || defined(__DragonFly__) || defined(_AIX) || \
132 defined(__GNU__) || (defined(__sun__) && defined(__svr4__))
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(__NetBSD__) || defined(__OpenBSD__) || defined(__minix) || \
237 defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(_AIX)
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(__sun__) && defined(__svr4__)
287 char exe_path[PATH_MAX];
288 const char *aPath = "/proc/self/execname";
289 if (sys::fs::exists(aPath)) {
290 int fd = open(aPath, O_RDONLY);
291 if (fd == -1)
292 return "";
293 if (read(fd, exe_path, sizeof(exe_path)) < 0)
294 return "";
295 return exe_path;
296 }
297 // Fall back to the classical detection.
298 if (getprogpath(exe_path, argv0) != NULL)
299 return exe_path;
300#elif defined(__MVS__)
301 int token = 0;
302 W_PSPROC buf;
303 char exe_path[PS_PATHBLEN];
304 pid_t pid = getpid();
305
306 memset(&buf, 0, sizeof(buf));
307 buf.ps_pathptr = exe_path;
308 buf.ps_pathlen = sizeof(exe_path);
309
310 while (true) {
311 if ((token = w_getpsent(token, &buf, sizeof(buf))) <= 0)
312 break;
313 if (buf.ps_pid != pid)
314 continue;
315 char real_path[PATH_MAX];
316 if (realpath(exe_path, real_path))
317 return std::string(real_path);
318 break; // Found entry, but realpath failed.
319 }
320#elif defined(HAVE_DLFCN_H) && defined(HAVE_DLADDR)
321 // Use dladdr to get executable path if available.
322 Dl_info DLInfo;
323 int err = dladdr(MainAddr, &DLInfo);
324 if (err == 0)
325 return "";
326
327 // If the filename is a symlink, we need to resolve and return the location of
328 // the actual executable.
329 char link_path[PATH_MAX];
330 if (realpath(DLInfo.dli_fname, link_path))
331 return link_path;
332#else
333#error GetMainExecutable is not implemented on this host yet.
334#endif
335 return "";
336}
337
340}
341
344}
345
346UniqueID file_status::getUniqueID() const {
347 return UniqueID(fs_st_dev, fs_st_ino);
348}
349
350uint32_t file_status::getLinkCount() const { return fs_st_nlinks; }
351
353 struct STATVFS Vfs;
354 if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs))
355 return std::error_code(errno, std::generic_category());
356 auto FrSize = STATVFS_F_FRSIZE(Vfs);
357 space_info SpaceInfo;
358 SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize;
359 SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize;
360 SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize;
361 return SpaceInfo;
362}
363
364std::error_code current_path(SmallVectorImpl<char> &result) {
365 result.clear();
366
367 const char *pwd = ::getenv("PWD");
368 llvm::sys::fs::file_status PWDStatus, DotStatus;
369 if (pwd && llvm::sys::path::is_absolute(pwd) &&
370 !llvm::sys::fs::status(pwd, PWDStatus) &&
371 !llvm::sys::fs::status(".", DotStatus) &&
372 PWDStatus.getUniqueID() == DotStatus.getUniqueID()) {
373 result.append(pwd, pwd + strlen(pwd));
374 return std::error_code();
375 }
376
377 result.resize_for_overwrite(PATH_MAX);
378
379 while (true) {
380 if (::getcwd(result.data(), result.size()) == nullptr) {
381 // See if there was a real error.
382 if (errno != ENOMEM) {
383 result.clear();
384 return std::error_code(errno, std::generic_category());
385 }
386 // Otherwise there just wasn't enough space.
387 result.resize_for_overwrite(result.capacity() * 2);
388 } else
389 break;
390 }
391
392 result.truncate(strlen(result.data()));
393 return std::error_code();
394}
395
396std::error_code set_current_path(const Twine &path) {
397 SmallString<128> path_storage;
398 StringRef p = path.toNullTerminatedStringRef(path_storage);
399
400 if (::chdir(p.begin()) == -1)
401 return std::error_code(errno, std::generic_category());
402
403 return std::error_code();
404}
405
406std::error_code create_directory(const Twine &path, bool IgnoreExisting,
407 perms Perms) {
408 SmallString<128> path_storage;
409 StringRef p = path.toNullTerminatedStringRef(path_storage);
410
411 if (::mkdir(p.begin(), Perms) == -1) {
412 if (errno != EEXIST || !IgnoreExisting)
413 return std::error_code(errno, std::generic_category());
414 }
415
416 return std::error_code();
417}
418
419// Note that we are using symbolic link because hard links are not supported by
420// all filesystems (SMB doesn't).
421std::error_code create_link(const Twine &to, const Twine &from) {
422 // Get arguments.
423 SmallString<128> from_storage;
424 SmallString<128> to_storage;
425 StringRef f = from.toNullTerminatedStringRef(from_storage);
426 StringRef t = to.toNullTerminatedStringRef(to_storage);
427
428 if (::symlink(t.begin(), f.begin()) == -1)
429 return std::error_code(errno, std::generic_category());
430
431 return std::error_code();
432}
433
434std::error_code create_hard_link(const Twine &to, const Twine &from) {
435 // Get arguments.
436 SmallString<128> from_storage;
437 SmallString<128> to_storage;
438 StringRef f = from.toNullTerminatedStringRef(from_storage);
439 StringRef t = to.toNullTerminatedStringRef(to_storage);
440
441 if (::link(t.begin(), f.begin()) == -1)
442 return std::error_code(errno, std::generic_category());
443
444 return std::error_code();
445}
446
447std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
448 SmallString<128> path_storage;
449 StringRef p = path.toNullTerminatedStringRef(path_storage);
450
451 struct stat buf;
452 if (lstat(p.begin(), &buf) != 0) {
453 if (errno != ENOENT || !IgnoreNonExisting)
454 return std::error_code(errno, std::generic_category());
455 return std::error_code();
456 }
457
458 // Note: this check catches strange situations. In all cases, LLVM should
459 // only be involved in the creation and deletion of regular files. This
460 // check ensures that what we're trying to erase is a regular file. It
461 // effectively prevents LLVM from erasing things like /dev/null, any block
462 // special file, or other things that aren't "regular" files.
463 if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode))
465
466 if (::remove(p.begin()) == -1) {
467 if (errno != ENOENT || !IgnoreNonExisting)
468 return std::error_code(errno, std::generic_category());
469 }
470
471 return std::error_code();
472}
473
474static bool is_local_impl(struct STATVFS &Vfs) {
475#if defined(__linux__) || defined(__GNU__)
476#ifndef NFS_SUPER_MAGIC
477#define NFS_SUPER_MAGIC 0x6969
478#endif
479#ifndef SMB_SUPER_MAGIC
480#define SMB_SUPER_MAGIC 0x517B
481#endif
482#ifndef CIFS_MAGIC_NUMBER
483#define CIFS_MAGIC_NUMBER 0xFF534D42
484#endif
485#ifdef __GNU__
486 switch ((uint32_t)Vfs.__f_type) {
487#else
488 switch ((uint32_t)Vfs.f_type) {
489#endif
490 case NFS_SUPER_MAGIC:
491 case SMB_SUPER_MAGIC:
492 case CIFS_MAGIC_NUMBER:
493 return false;
494 default:
495 return true;
496 }
497#elif defined(__CYGWIN__)
498 // Cygwin doesn't expose this information; would need to use Win32 API.
499 return false;
500#elif defined(__Fuchsia__)
501 // Fuchsia doesn't yet support remote filesystem mounts.
502 return true;
503#elif defined(__EMSCRIPTEN__)
504 // Emscripten doesn't currently support remote filesystem mounts.
505 return true;
506#elif defined(__HAIKU__)
507 // Haiku doesn't expose this information.
508 return false;
509#elif defined(__sun)
510 // statvfs::f_basetype contains a null-terminated FSType name of the mounted
511 // target
512 StringRef fstype(Vfs.f_basetype);
513 // NFS is the only non-local fstype??
514 return !fstype.equals("nfs");
515#elif defined(_AIX)
516 // Call mntctl; try more than twice in case of timing issues with a concurrent
517 // mount.
518 int Ret;
519 size_t BufSize = 2048u;
520 std::unique_ptr<char[]> Buf;
521 int Tries = 3;
522 while (Tries--) {
523 Buf = std::make_unique<char[]>(BufSize);
524 Ret = mntctl(MCTL_QUERY, BufSize, Buf.get());
525 if (Ret != 0)
526 break;
527 BufSize = *reinterpret_cast<unsigned int *>(Buf.get());
528 Buf.reset();
529 }
530
531 if (Ret == -1)
532 // There was an error; "remote" is the conservative answer.
533 return false;
534
535 // Look for the correct vmount entry.
536 char *CurObjPtr = Buf.get();
537 while (Ret--) {
538 struct vmount *Vp = reinterpret_cast<struct vmount *>(CurObjPtr);
539 static_assert(sizeof(Vfs.f_fsid) == sizeof(Vp->vmt_fsid),
540 "fsid length mismatch");
541 if (memcmp(&Vfs.f_fsid, &Vp->vmt_fsid, sizeof Vfs.f_fsid) == 0)
542 return (Vp->vmt_flags & MNT_REMOTE) == 0;
543
544 CurObjPtr += Vp->vmt_length;
545 }
546
547 // vmount entry not found; "remote" is the conservative answer.
548 return false;
549#elif defined(__MVS__)
550 // The file system can have an arbitrary structure on z/OS; must go with the
551 // conservative answer.
552 return false;
553#else
554 return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL);
555#endif
556}
557
558std::error_code is_local(const Twine &Path, bool &Result) {
559 struct STATVFS Vfs;
560 if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs))
561 return std::error_code(errno, std::generic_category());
562
563 Result = is_local_impl(Vfs);
564 return std::error_code();
565}
566
567std::error_code is_local(int FD, bool &Result) {
568 struct STATVFS Vfs;
569 if (::FSTATVFS(FD, &Vfs))
570 return std::error_code(errno, std::generic_category());
571
572 Result = is_local_impl(Vfs);
573 return std::error_code();
574}
575
576std::error_code rename(const Twine &from, const Twine &to) {
577 // Get arguments.
578 SmallString<128> from_storage;
579 SmallString<128> to_storage;
580 StringRef f = from.toNullTerminatedStringRef(from_storage);
581 StringRef t = to.toNullTerminatedStringRef(to_storage);
582
583 if (::rename(f.begin(), t.begin()) == -1)
584 return std::error_code(errno, std::generic_category());
585
586 return std::error_code();
587}
588
589std::error_code resize_file(int FD, uint64_t Size) {
590 // Use ftruncate as a fallback. It may or may not allocate space. At least on
591 // OS X with HFS+ it does.
592 if (::ftruncate(FD, Size) == -1)
593 return std::error_code(errno, std::generic_category());
594
595 return std::error_code();
596}
597
598static int convertAccessMode(AccessMode Mode) {
599 switch (Mode) {
601 return F_OK;
603 return W_OK;
605 return R_OK | X_OK; // scripts also need R_OK.
606 }
607 llvm_unreachable("invalid enum");
608}
609
610std::error_code access(const Twine &Path, AccessMode Mode) {
611 SmallString<128> PathStorage;
612 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
613
614 if (::access(P.begin(), convertAccessMode(Mode)) == -1)
615 return std::error_code(errno, std::generic_category());
616
617 if (Mode == AccessMode::Execute) {
618 // Don't say that directories are executable.
619 struct stat buf;
620 if (0 != stat(P.begin(), &buf))
622 if (!S_ISREG(buf.st_mode))
624 }
625
626 return std::error_code();
627}
628
629bool can_execute(const Twine &Path) {
630 return !access(Path, AccessMode::Execute);
631}
632
633bool equivalent(file_status A, file_status B) {
635 return A.fs_st_dev == B.fs_st_dev && A.fs_st_ino == B.fs_st_ino;
636}
637
638std::error_code equivalent(const Twine &A, const Twine &B, bool &result) {
639 file_status fsA, fsB;
640 if (std::error_code ec = status(A, fsA))
641 return ec;
642 if (std::error_code ec = status(B, fsB))
643 return ec;
644 result = equivalent(fsA, fsB);
645 return std::error_code();
646}
647
648static void expandTildeExpr(SmallVectorImpl<char> &Path) {
649 StringRef PathStr(Path.begin(), Path.size());
650 if (PathStr.empty() || !PathStr.startswith("~"))
651 return;
652
653 PathStr = PathStr.drop_front();
654 StringRef Expr =
655 PathStr.take_until([](char c) { return path::is_separator(c); });
656 StringRef Remainder = PathStr.substr(Expr.size() + 1);
657 SmallString<128> Storage;
658 if (Expr.empty()) {
659 // This is just ~/..., resolve it to the current user's home dir.
660 if (!path::home_directory(Storage)) {
661 // For some reason we couldn't get the home directory. Just exit.
662 return;
663 }
664
665 // Overwrite the first character and insert the rest.
666 Path[0] = Storage[0];
667 Path.insert(Path.begin() + 1, Storage.begin() + 1, Storage.end());
668 return;
669 }
670
671 // This is a string of the form ~username/, look up this user's entry in the
672 // password database.
673 std::unique_ptr<char[]> Buf;
674 long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
675 if (BufSize <= 0)
676 BufSize = 16384;
677 Buf = std::make_unique<char[]>(BufSize);
678 struct passwd Pwd;
679 std::string User = Expr.str();
680 struct passwd *Entry = nullptr;
681 getpwnam_r(User.c_str(), &Pwd, Buf.get(), BufSize, &Entry);
682
683 if (!Entry || !Entry->pw_dir) {
684 // Unable to look up the entry, just return back the original path.
685 return;
686 }
687
688 Storage = Remainder;
689 Path.clear();
690 Path.append(Entry->pw_dir, Entry->pw_dir + strlen(Entry->pw_dir));
691 llvm::sys::path::append(Path, Storage);
692}
693
694void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) {
695 dest.clear();
696 if (path.isTriviallyEmpty())
697 return;
698
699 path.toVector(dest);
700 expandTildeExpr(dest);
701}
702
703static file_type typeForMode(mode_t Mode) {
704 if (S_ISDIR(Mode))
706 else if (S_ISREG(Mode))
708 else if (S_ISBLK(Mode))
710 else if (S_ISCHR(Mode))
712 else if (S_ISFIFO(Mode))
714 else if (S_ISSOCK(Mode))
716 else if (S_ISLNK(Mode))
719}
720
721static std::error_code fillStatus(int StatRet, const struct stat &Status,
722 file_status &Result) {
723 if (StatRet != 0) {
724 std::error_code EC(errno, std::generic_category());
726 Result = file_status(file_type::file_not_found);
727 else
728 Result = file_status(file_type::status_error);
729 return EC;
730 }
731
732 uint32_t atime_nsec, mtime_nsec;
733#if defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
734 atime_nsec = Status.st_atimespec.tv_nsec;
735 mtime_nsec = Status.st_mtimespec.tv_nsec;
736#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC)
737 atime_nsec = Status.st_atim.tv_nsec;
738 mtime_nsec = Status.st_mtim.tv_nsec;
739#else
740 atime_nsec = mtime_nsec = 0;
741#endif
742
743 perms Perms = static_cast<perms>(Status.st_mode) & all_perms;
744 Result = file_status(typeForMode(Status.st_mode), Perms, Status.st_dev,
745 Status.st_nlink, Status.st_ino, Status.st_atime,
746 atime_nsec, Status.st_mtime, mtime_nsec, Status.st_uid,
747 Status.st_gid, Status.st_size);
748
749 return std::error_code();
750}
751
752std::error_code status(const Twine &Path, file_status &Result, bool Follow) {
753 SmallString<128> PathStorage;
754 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
755
756 struct stat Status;
757 int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status);
758 return fillStatus(StatRet, Status, Result);
759}
760
761std::error_code status(int FD, file_status &Result) {
762 struct stat Status;
763 int StatRet = ::fstat(FD, &Status);
764 return fillStatus(StatRet, Status, Result);
765}
766
767unsigned getUmask() {
768 // Chose arbitary new mask and reset the umask to the old mask.
769 // umask(2) never fails so ignore the return of the second call.
770 unsigned Mask = ::umask(0);
771 (void)::umask(Mask);
772 return Mask;
773}
774
775std::error_code setPermissions(const Twine &Path, perms Permissions) {
776 SmallString<128> PathStorage;
777 StringRef P = Path.toNullTerminatedStringRef(PathStorage);
778
779 if (::chmod(P.begin(), Permissions))
780 return std::error_code(errno, std::generic_category());
781 return std::error_code();
782}
783
784std::error_code setPermissions(int FD, perms Permissions) {
785 if (::fchmod(FD, Permissions))
786 return std::error_code(errno, std::generic_category());
787 return std::error_code();
788}
789
790std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime,
791 TimePoint<> ModificationTime) {
792#if defined(HAVE_FUTIMENS)
793 timespec Times[2];
794 Times[0] = sys::toTimeSpec(AccessTime);
795 Times[1] = sys::toTimeSpec(ModificationTime);
796 if (::futimens(FD, Times))
797 return std::error_code(errno, std::generic_category());
798 return std::error_code();
799#elif defined(HAVE_FUTIMES)
800 timeval Times[2];
801 Times[0] = sys::toTimeVal(
802 std::chrono::time_point_cast<std::chrono::microseconds>(AccessTime));
803 Times[1] =
804 sys::toTimeVal(std::chrono::time_point_cast<std::chrono::microseconds>(
805 ModificationTime));
806 if (::futimes(FD, Times))
807 return std::error_code(errno, std::generic_category());
808 return std::error_code();
809#elif defined(__MVS__)
810 attrib_t Attr;
811 memset(&Attr, 0, sizeof(Attr));
812 Attr.att_atimechg = 1;
813 Attr.att_atime = sys::toTimeT(AccessTime);
814 Attr.att_mtimechg = 1;
815 Attr.att_mtime = sys::toTimeT(ModificationTime);
816 if (::__fchattr(FD, &Attr, sizeof(Attr)) != 0)
817 return std::error_code(errno, std::generic_category());
818 return std::error_code();
819#else
820#warning Missing futimes() and futimens()
822#endif
823}
824
825std::error_code mapped_file_region::init(int FD, uint64_t Offset,
826 mapmode Mode) {
827 assert(Size != 0);
828
829 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE;
830 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE);
831#if defined(MAP_NORESERVE)
832 flags |= MAP_NORESERVE;
833#endif
834#if defined(__APPLE__)
835 //----------------------------------------------------------------------
836 // Newer versions of MacOSX have a flag that will allow us to read from
837 // binaries whose code signature is invalid without crashing by using
838 // the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media
839 // is mapped we can avoid crashing and return zeroes to any pages we try
840 // to read if the media becomes unavailable by using the
841 // MAP_RESILIENT_MEDIA flag. These flags are only usable when mapping
842 // with PROT_READ, so take care not to specify them otherwise.
843 //----------------------------------------------------------------------
844 if (Mode == readonly) {
845#if defined(MAP_RESILIENT_CODESIGN)
846 flags |= MAP_RESILIENT_CODESIGN;
847#endif
848#if defined(MAP_RESILIENT_MEDIA)
849 flags |= MAP_RESILIENT_MEDIA;
850#endif
851 }
852#endif // #if defined (__APPLE__)
853
854 Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset);
855 if (Mapping == MAP_FAILED)
856 return std::error_code(errno, std::generic_category());
857 return std::error_code();
858}
859
860mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length,
861 uint64_t offset, std::error_code &ec)
862 : Size(length), Mode(mode) {
863 (void)Mode;
864 ec = init(fd, offset, mode);
865 if (ec)
866 copyFrom(mapped_file_region());
867}
868
869void mapped_file_region::unmapImpl() {
870 if (Mapping)
871 ::munmap(Mapping, Size);
872}
873
874void mapped_file_region::dontNeedImpl() {
875 assert(Mode == mapped_file_region::readonly);
876 if (!Mapping)
877 return;
878#if defined(__MVS__) || defined(_AIX)
879 // If we don't have madvise, or it isn't beneficial, treat this as a no-op.
880#elif defined(POSIX_MADV_DONTNEED)
881 ::posix_madvise(Mapping, Size, POSIX_MADV_DONTNEED);
882#else
883 ::madvise(Mapping, Size, MADV_DONTNEED);
884#endif
885}
886
887int mapped_file_region::alignment() { return Process::getPageSizeEstimate(); }
888
889std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
890 StringRef path,
891 bool follow_symlinks) {
892 SmallString<128> path_null(path);
893 DIR *directory = ::opendir(path_null.c_str());
894 if (!directory)
895 return std::error_code(errno, std::generic_category());
896
897 it.IterationHandle = reinterpret_cast<intptr_t>(directory);
898 // Add something for replace_filename to replace.
899 path::append(path_null, ".");
900 it.CurrentEntry = directory_entry(path_null.str(), follow_symlinks);
902}
903
904std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) {
905 if (it.IterationHandle)
906 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle));
907 it.IterationHandle = 0;
908 it.CurrentEntry = directory_entry();
909 return std::error_code();
910}
911
912static file_type direntType(dirent *Entry) {
913 // Most platforms provide the file type in the dirent: Linux/BSD/Mac.
914 // The DTTOIF macro lets us reuse our status -> type conversion.
915 // Note that while glibc provides a macro to see if this is supported,
916 // _DIRENT_HAVE_D_TYPE, it's not defined on BSD/Mac, so we test for the
917 // d_type-to-mode_t conversion macro instead.
918#if defined(DTTOIF)
919 return typeForMode(DTTOIF(Entry->d_type));
920#else
921 // Other platforms such as Solaris require a stat() to get the type.
922 return file_type::type_unknown;
923#endif
924}
925
926std::error_code detail::directory_iterator_increment(detail::DirIterState &It) {
927 errno = 0;
928 dirent *CurDir = ::readdir(reinterpret_cast<DIR *>(It.IterationHandle));
929 if (CurDir == nullptr && errno != 0) {
930 return std::error_code(errno, std::generic_category());
931 } else if (CurDir != nullptr) {
932 StringRef Name(CurDir->d_name);
933 if ((Name.size() == 1 && Name[0] == '.') ||
934 (Name.size() == 2 && Name[0] == '.' && Name[1] == '.'))
936 It.CurrentEntry.replace_filename(Name, direntType(CurDir));
937 } else
939
940 return std::error_code();
941}
942
943ErrorOr<basic_file_status> directory_entry::status() const {
944 file_status s;
945 if (auto EC = fs::status(Path, s, FollowSymlinks))
946 return EC;
947 return s;
948}
949
950//
951// FreeBSD optionally provides /proc/self/fd, but it is incompatible with
952// Linux. The thing to use is realpath.
953//
954#if !defined(__FreeBSD__)
955#define TRY_PROC_SELF_FD
956#endif
957
958#if !defined(F_GETPATH) && defined(TRY_PROC_SELF_FD)
959static bool hasProcSelfFD() {
960 // If we have a /proc filesystem mounted, we can quickly establish the
961 // real name of the file with readlink
962 static const bool Result = (::access("/proc/self/fd", R_OK) == 0);
963 return Result;
964}
965#endif
966
967static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags,
968 FileAccess Access) {
969 int Result = 0;
970 if (Access == FA_Read)
971 Result |= O_RDONLY;
972 else if (Access == FA_Write)
973 Result |= O_WRONLY;
974 else if (Access == (FA_Read | FA_Write))
975 Result |= O_RDWR;
976
977 // This is for compatibility with old code that assumed OF_Append implied
978 // would open an existing file. See Windows/Path.inc for a longer comment.
979 if (Flags & OF_Append)
980 Disp = CD_OpenAlways;
981
982 if (Disp == CD_CreateNew) {
983 Result |= O_CREAT; // Create if it doesn't exist.
984 Result |= O_EXCL; // Fail if it does.
985 } else if (Disp == CD_CreateAlways) {
986 Result |= O_CREAT; // Create if it doesn't exist.
987 Result |= O_TRUNC; // Truncate if it does.
988 } else if (Disp == CD_OpenAlways) {
989 Result |= O_CREAT; // Create if it doesn't exist.
990 } else if (Disp == CD_OpenExisting) {
991 // Nothing special, just don't add O_CREAT and we get these semantics.
992 }
993
994// Using append mode with z/OS UTF-8 auto-conversion results in EINVAL when
995// calling write(). Instead we need to use lseek() to set offset to EOF after
996// open().
997#ifndef __MVS__
998 if (Flags & OF_Append)
999 Result |= O_APPEND;
1000#endif
1001
1002#ifdef O_CLOEXEC
1003 if (!(Flags & OF_ChildInherit))
1004 Result |= O_CLOEXEC;
1005#endif
1006
1007 return Result;
1008}
1009
1010std::error_code openFile(const Twine &Name, int &ResultFD,
1011 CreationDisposition Disp, FileAccess Access,
1012 OpenFlags Flags, unsigned Mode) {
1013 int OpenFlags = nativeOpenFlags(Disp, Flags, Access);
1014
1015 SmallString<128> Storage;
1016 StringRef P = Name.toNullTerminatedStringRef(Storage);
1017 // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal
1018 // when open is overloaded, such as in Bionic.
1019 auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); };
1020 if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0)
1021 return std::error_code(errno, std::generic_category());
1022#ifndef O_CLOEXEC
1023 if (!(Flags & OF_ChildInherit)) {
1024 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC);
1025 (void)r;
1026 assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed");
1027 }
1028#endif
1029
1030#ifdef __MVS__
1031 /* Reason about auto-conversion and file tags. Setting the file tag only
1032 * applies if file is opened in write mode:
1033 *
1034 * Text file:
1035 * File exists File created
1036 * CD_CreateNew n/a conv: on
1037 * tag: set 1047
1038 * CD_CreateAlways conv: auto conv: on
1039 * tag: auto 1047 tag: set 1047
1040 * CD_OpenAlways conv: auto conv: on
1041 * tag: auto 1047 tag: set 1047
1042 * CD_OpenExisting conv: auto n/a
1043 * tag: unchanged
1044 *
1045 * Binary file:
1046 * File exists File created
1047 * CD_CreateNew n/a conv: off
1048 * tag: set binary
1049 * CD_CreateAlways conv: off conv: off
1050 * tag: auto binary tag: set binary
1051 * CD_OpenAlways conv: off conv: off
1052 * tag: auto binary tag: set binary
1053 * CD_OpenExisting conv: off n/a
1054 * tag: unchanged
1055 *
1056 * Actions:
1057 * conv: off -> auto-conversion is turned off
1058 * conv: on -> auto-conversion is turned on
1059 * conv: auto -> auto-conversion is turned on if the file is untagged
1060 * tag: set 1047 -> set the file tag to text encoded in 1047
1061 * tag: set binary -> set the file tag to binary
1062 * tag: auto 1047 -> set file tag to 1047 if not set
1063 * tag: auto binary -> set file tag to binary if not set
1064 * tag: unchanged -> do not care about the file tag
1065 *
1066 * It is not possible to distinguish between the cases "file exists" and
1067 * "file created". In the latter case, the file tag is not set and the file
1068 * size is zero. The decision table boils down to:
1069 *
1070 * the file tag is set if
1071 * - the file is opened for writing
1072 * - the create disposition is not equal to CD_OpenExisting
1073 * - the file tag is not set
1074 * - the file size is zero
1075 *
1076 * This only applies if the file is a regular file. E.g. enabling
1077 * auto-conversion for reading from /dev/null results in error EINVAL when
1078 * calling read().
1079 *
1080 * Using append mode with z/OS UTF-8 auto-conversion results in EINVAL when
1081 * calling write(). Instead we need to use lseek() to set offset to EOF after
1082 * open().
1083 */
1084 if ((Flags & OF_Append) && lseek(ResultFD, 0, SEEK_END) == -1)
1085 return std::error_code(errno, std::generic_category());
1086 struct stat Stat;
1087 if (fstat(ResultFD, &Stat) == -1)
1088 return std::error_code(errno, std::generic_category());
1089 if (S_ISREG(Stat.st_mode)) {
1090 bool DoSetTag = (Access & FA_Write) && (Disp != CD_OpenExisting) &&
1091 !Stat.st_tag.ft_txtflag && !Stat.st_tag.ft_ccsid &&
1092 Stat.st_size == 0;
1093 if (Flags & OF_Text) {
1094 if (auto EC = llvm::enableAutoConversion(ResultFD))
1095 return EC;
1096 if (DoSetTag) {
1097 if (auto EC = llvm::setFileTag(ResultFD, CCSID_IBM_1047, true))
1098 return EC;
1099 }
1100 } else {
1101 if (auto EC = llvm::disableAutoConversion(ResultFD))
1102 return EC;
1103 if (DoSetTag) {
1104 if (auto EC = llvm::setFileTag(ResultFD, FT_BINARY, false))
1105 return EC;
1106 }
1107 }
1108 }
1109#endif
1110
1111 return std::error_code();
1112}
1113
1114Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp,
1115 FileAccess Access, OpenFlags Flags,
1116 unsigned Mode) {
1117
1118 int FD;
1119 std::error_code EC = openFile(Name, FD, Disp, Access, Flags, Mode);
1120 if (EC)
1121 return errorCodeToError(EC);
1122 return FD;
1123}
1124
1125std::error_code openFileForRead(const Twine &Name, int &ResultFD,
1126 OpenFlags Flags,
1127 SmallVectorImpl<char> *RealPath) {
1128 std::error_code EC =
1129 openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666);
1130 if (EC)
1131 return EC;
1132
1133 // Attempt to get the real name of the file, if the user asked
1134 if (!RealPath)
1135 return std::error_code();
1136 RealPath->clear();
1137#if defined(F_GETPATH)
1138 // When F_GETPATH is availble, it is the quickest way to get
1139 // the real path name.
1140 char Buffer[PATH_MAX];
1141 if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1)
1142 RealPath->append(Buffer, Buffer + strlen(Buffer));
1143#else
1144 char Buffer[PATH_MAX];
1145#if defined(TRY_PROC_SELF_FD)
1146 if (hasProcSelfFD()) {
1147 char ProcPath[64];
1148 snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD);
1149 ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer));
1150 if (CharCount > 0)
1151 RealPath->append(Buffer, Buffer + CharCount);
1152 } else {
1153#endif
1154 SmallString<128> Storage;
1155 StringRef P = Name.toNullTerminatedStringRef(Storage);
1156
1157 // Use ::realpath to get the real path name
1158 if (::realpath(P.begin(), Buffer) != nullptr)
1159 RealPath->append(Buffer, Buffer + strlen(Buffer));
1160#if defined(TRY_PROC_SELF_FD)
1161 }
1162#endif
1163#endif
1164 return std::error_code();
1165}
1166
1168 SmallVectorImpl<char> *RealPath) {
1169 file_t ResultFD;
1170 std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath);
1171 if (EC)
1172 return errorCodeToError(EC);
1173 return ResultFD;
1174}
1175
1176file_t getStdinHandle() { return 0; }
1177file_t getStdoutHandle() { return 1; }
1178file_t getStderrHandle() { return 2; }
1179
1181#if defined(__APPLE__)
1182 size_t Size = std::min<size_t>(Buf.size(), INT32_MAX);
1183#else
1184 size_t Size = Buf.size();
1185#endif
1186 ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size);
1187 if (ssize_t(NumRead) == -1)
1188 return errorCodeToError(std::error_code(errno, std::generic_category()));
1189 return NumRead;
1190}
1191
1193 uint64_t Offset) {
1194#if defined(__APPLE__)
1195 size_t Size = std::min<size_t>(Buf.size(), INT32_MAX);
1196#else
1197 size_t Size = Buf.size();
1198#endif
1199#ifdef HAVE_PREAD
1200 ssize_t NumRead =
1201 sys::RetryAfterSignal(-1, ::pread, FD, Buf.data(), Size, Offset);
1202#else
1203 if (lseek(FD, Offset, SEEK_SET) == -1)
1204 return errorCodeToError(std::error_code(errno, std::generic_category()));
1205 ssize_t NumRead = sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size);
1206#endif
1207 if (NumRead == -1)
1208 return errorCodeToError(std::error_code(errno, std::generic_category()));
1209 return NumRead;
1210}
1211
1212std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout) {
1213 auto Start = std::chrono::steady_clock::now();
1214 auto End = Start + Timeout;
1215 do {
1216 struct flock Lock;
1217 memset(&Lock, 0, sizeof(Lock));
1218 Lock.l_type = F_WRLCK;
1219 Lock.l_whence = SEEK_SET;
1220 Lock.l_start = 0;
1221 Lock.l_len = 0;
1222 if (::fcntl(FD, F_SETLK, &Lock) != -1)
1223 return std::error_code();
1224 int Error = errno;
1225 if (Error != EACCES && Error != EAGAIN)
1226 return std::error_code(Error, std::generic_category());
1227 usleep(1000);
1228 } while (std::chrono::steady_clock::now() < End);
1229 return make_error_code(errc::no_lock_available);
1230}
1231
1232std::error_code lockFile(int FD) {
1233 struct flock Lock;
1234 memset(&Lock, 0, sizeof(Lock));
1235 Lock.l_type = F_WRLCK;
1236 Lock.l_whence = SEEK_SET;
1237 Lock.l_start = 0;
1238 Lock.l_len = 0;
1239 if (::fcntl(FD, F_SETLKW, &Lock) != -1)
1240 return std::error_code();
1241 int Error = errno;
1242 return std::error_code(Error, std::generic_category());
1243}
1244
1245std::error_code unlockFile(int FD) {
1246 struct flock Lock;
1247 Lock.l_type = F_UNLCK;
1248 Lock.l_whence = SEEK_SET;
1249 Lock.l_start = 0;
1250 Lock.l_len = 0;
1251 if (::fcntl(FD, F_SETLK, &Lock) != -1)
1252 return std::error_code();
1253 return std::error_code(errno, std::generic_category());
1254}
1255
1256std::error_code closeFile(file_t &F) {
1257 file_t TmpF = F;
1258 F = kInvalidFile;
1259 return Process::SafelyCloseFileDescriptor(TmpF);
1260}
1261
1262template <typename T>
1263static std::error_code remove_directories_impl(const T &Entry,
1264 bool IgnoreErrors) {
1265 std::error_code EC;
1266 directory_iterator Begin(Entry, EC, false);
1267 directory_iterator End;
1268 while (Begin != End) {
1269 auto &Item = *Begin;
1270 ErrorOr<basic_file_status> st = Item.status();
1271 if (st) {
1272 if (is_directory(*st)) {
1273 EC = remove_directories_impl(Item, IgnoreErrors);
1274 if (EC && !IgnoreErrors)
1275 return EC;
1276 }
1277
1278 EC = fs::remove(Item.path(), true);
1279 if (EC && !IgnoreErrors)
1280 return EC;
1281 } else if (!IgnoreErrors) {
1282 return st.getError();
1283 }
1284
1285 Begin.increment(EC);
1286 if (EC && !IgnoreErrors)
1287 return EC;
1288 }
1289 return std::error_code();
1290}
1291
1292std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
1293 auto EC = remove_directories_impl(path, IgnoreErrors);
1294 if (EC && !IgnoreErrors)
1295 return EC;
1296 EC = fs::remove(path, true);
1297 if (EC && !IgnoreErrors)
1298 return EC;
1299 return std::error_code();
1300}
1301
1302std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
1303 bool expand_tilde) {
1304 dest.clear();
1305 if (path.isTriviallyEmpty())
1306 return std::error_code();
1307
1308 if (expand_tilde) {
1309 SmallString<128> Storage;
1310 path.toVector(Storage);
1311 expandTildeExpr(Storage);
1312 return real_path(Storage, dest, false);
1313 }
1314
1315 SmallString<128> Storage;
1316 StringRef P = path.toNullTerminatedStringRef(Storage);
1317 char Buffer[PATH_MAX];
1318 if (::realpath(P.begin(), Buffer) == nullptr)
1319 return std::error_code(errno, std::generic_category());
1320 dest.append(Buffer, Buffer + strlen(Buffer));
1321 return std::error_code();
1322}
1323
1324std::error_code changeFileOwnership(int FD, uint32_t Owner, uint32_t Group) {
1325 auto FChown = [&]() { return ::fchown(FD, Owner, Group); };
1326 // Retry if fchown call fails due to interruption.
1327 if ((sys::RetryAfterSignal(-1, FChown)) < 0)
1328 return std::error_code(errno, std::generic_category());
1329 return std::error_code();
1330}
1331
1332} // end namespace fs
1333
1334namespace path {
1335
1337 std::unique_ptr<char[]> Buf;
1338 char *RequestedDir = getenv("HOME");
1339 if (!RequestedDir) {
1340 long BufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
1341 if (BufSize <= 0)
1342 BufSize = 16384;
1343 Buf = std::make_unique<char[]>(BufSize);
1344 struct passwd Pwd;
1345 struct passwd *pw = nullptr;
1346 getpwuid_r(getuid(), &Pwd, Buf.get(), BufSize, &pw);
1347 if (pw && pw->pw_dir)
1348 RequestedDir = pw->pw_dir;
1349 }
1350 if (!RequestedDir)
1351 return false;
1352
1353 result.clear();
1354 result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1355 return true;
1356}
1357
1358static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) {
1359#if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR)
1360 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR.
1361 // macros defined in <unistd.h> on darwin >= 9
1362 int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR : _CS_DARWIN_USER_CACHE_DIR;
1363 size_t ConfLen = confstr(ConfName, nullptr, 0);
1364 if (ConfLen > 0) {
1365 do {
1366 Result.resize(ConfLen);
1367 ConfLen = confstr(ConfName, Result.data(), Result.size());
1368 } while (ConfLen > 0 && ConfLen != Result.size());
1369
1370 if (ConfLen > 0) {
1371 assert(Result.back() == 0);
1372 Result.pop_back();
1373 return true;
1374 }
1375
1376 Result.clear();
1377 }
1378#endif
1379 return false;
1380}
1381
1383#ifdef __APPLE__
1384 // Mac: ~/Library/Preferences/
1385 if (home_directory(result)) {
1386 append(result, "Library", "Preferences");
1387 return true;
1388 }
1389#else
1390 // XDG_CONFIG_HOME as defined in the XDG Base Directory Specification:
1391 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
1392 if (const char *RequestedDir = getenv("XDG_CONFIG_HOME")) {
1393 result.clear();
1394 result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1395 return true;
1396 }
1397#endif
1398 // Fallback: ~/.config
1399 if (!home_directory(result)) {
1400 return false;
1401 }
1402 append(result, ".config");
1403 return true;
1404}
1405
1407#ifdef __APPLE__
1408 if (getDarwinConfDir(false /*tempDir*/, result)) {
1409 return true;
1410 }
1411#else
1412 // XDG_CACHE_HOME as defined in the XDG Base Directory Specification:
1413 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
1414 if (const char *RequestedDir = getenv("XDG_CACHE_HOME")) {
1415 result.clear();
1416 result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1417 return true;
1418 }
1419#endif
1420 if (!home_directory(result)) {
1421 return false;
1422 }
1423 append(result, ".cache");
1424 return true;
1425}
1426
1427static const char *getEnvTempDir() {
1428 // Check whether the temporary directory is specified by an environment
1429 // variable.
1430 const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
1431 for (const char *Env : EnvironmentVariables) {
1432 if (const char *Dir = std::getenv(Env))
1433 return Dir;
1434 }
1435
1436 return nullptr;
1437}
1438
1439static const char *getDefaultTempDir(bool ErasedOnReboot) {
1440#ifdef P_tmpdir
1441 if ((bool)P_tmpdir)
1442 return P_tmpdir;
1443#endif
1444
1445 if (ErasedOnReboot)
1446 return "/tmp";
1447 return "/var/tmp";
1448}
1449
1450void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
1451 Result.clear();
1452
1453 if (ErasedOnReboot) {
1454 // There is no env variable for the cache directory.
1455 if (const char *RequestedDir = getEnvTempDir()) {
1456 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1457 return;
1458 }
1459 }
1460
1461 if (getDarwinConfDir(ErasedOnReboot, Result))
1462 return;
1463
1464 const char *RequestedDir = getDefaultTempDir(ErasedOnReboot);
1465 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir));
1466}
1467
1468} // end namespace path
1469
1470namespace fs {
1471
1472#ifdef __APPLE__
1473/// This implementation tries to perform an APFS CoW clone of the file,
1474/// which can be much faster and uses less space.
1475/// Unfortunately fcopyfile(3) does not support COPYFILE_CLONE, so the
1476/// file descriptor variant of this function still uses the default
1477/// implementation.
1478std::error_code copy_file(const Twine &From, const Twine &To) {
1479 std::string FromS = From.str();
1480 std::string ToS = To.str();
1481#if __has_builtin(__builtin_available)
1482 if (__builtin_available(macos 10.12, *)) {
1483 // Optimistically try to use clonefile() and handle errors, rather than
1484 // calling stat() to see if it'll work.
1485 //
1486 // Note: It's okay if From is a symlink. In contrast to the behaviour of
1487 // copyfile() with COPYFILE_CLONE, clonefile() clones targets (not the
1488 // symlink itself) unless the flag CLONE_NOFOLLOW is passed.
1489 if (!clonefile(FromS.c_str(), ToS.c_str(), 0))
1490 return std::error_code();
1491
1492 auto Errno = errno;
1493 switch (Errno) {
1494 case EEXIST: // To already exists.
1495 case ENOTSUP: // Device does not support cloning.
1496 case EXDEV: // From and To are on different devices.
1497 break;
1498 default:
1499 // Anything else will also break copyfile().
1500 return std::error_code(Errno, std::generic_category());
1501 }
1502
1503 // TODO: For EEXIST, profile calling fs::generateUniqueName() and
1504 // clonefile() in a retry loop (then rename() on success) before falling
1505 // back to copyfile(). Depending on the size of the file this could be
1506 // cheaper.
1507 }
1508#endif
1509 if (!copyfile(FromS.c_str(), ToS.c_str(), /*State=*/NULL, COPYFILE_DATA))
1510 return std::error_code();
1511 return std::error_code(errno, std::generic_category());
1512}
1513#endif // __APPLE__
1514
1515} // end namespace fs
1516
1517} // end namespace sys
1518} // 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:464
uint64_t Offset
Definition: ELF_riscv.cpp:462
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:953
#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())
@ Flags
Definition: TextStubV5.cpp:93
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
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:156
Tagged union holding either a T or a Error.
Definition: Error.h:470
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:305
T * data() const
Definition: ArrayRef.h:352
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:577
void resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
Definition: SmallVector.h:645
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:687
void truncate(size_type N)
Like resize, but requires that N is less than size().
Definition: SmallVector.h:648
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:289
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:569
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:601
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:417
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:1272
@ readwrite
May access map via data and modify it. Written to path.
Definition: FileSystem.h:1273
#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:119
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:445
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition: Endian.h:63
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:748
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:45
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:37
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:406
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:1777
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:92