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