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 <mach-o/dyld.h> 40#include <sys/attr.h> 41#include <copyfile.h> 42#elif defined(__FreeBSD__) 43#include <osreldate.h> 44#if __FreeBSD_version >= 1300057 45#include <sys/auxv.h> 46#else 47#include <machine/elf.h> 48extern char **environ; 49#endif 50#elif defined(__DragonFly__) 51#include <sys/mount.h> 52#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(__minix) || defined(__FreeBSD_kernel__) || defined(__linux__) || \ 127 defined(__CYGWIN__) || defined(__DragonFly__) || defined(_AIX) || defined(__GNU__) 128static int 129test_dir(char ret[PATH_MAX], const char *dir, const char *bin) 130{ 131 struct stat sb; 132 char fullpath[PATH_MAX]; 133 134 int chars = snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); 135 // We cannot write PATH_MAX characters because the string will be terminated 136 // with a null character. Fail if truncation happened. 137 if (chars >= PATH_MAX) 138 return 1; 139 if (!realpath(fullpath, ret)) 140 return 1; 141 if (stat(fullpath, &sb) != 0) 142 return 1; 143 144 return 0; 145} 146 147static char * 148getprogpath(char ret[PATH_MAX], const char *bin) 149{ 150 if (bin == nullptr) 151 return nullptr; 152 153 /* First approach: absolute path. */ 154 if (bin[0] == '/') { 155 if (test_dir(ret, "/", bin) == 0) 156 return ret; 157 return nullptr; 158 } 159 160 /* Second approach: relative path. */ 161 if (strchr(bin, '/')) { 162 char cwd[PATH_MAX]; 163 if (!getcwd(cwd, PATH_MAX)) 164 return nullptr; 165 if (test_dir(ret, cwd, bin) == 0) 166 return ret; 167 return nullptr; 168 } 169 170 /* Third approach: $PATH */ 171 char *pv; 172 if ((pv = getenv("PATH")) == nullptr) 173 return nullptr; 174 char *s = strdup(pv); 175 if (!s) 176 return nullptr; 177 char *state; 178 for (char *t = strtok_r(s, ":", &state); t != nullptr; 179 t = strtok_r(nullptr, ":", &state)) { 180 if (test_dir(ret, t, bin) == 0) { 181 free(s); 182 return ret; 183 } 184 } 185 free(s); 186 return nullptr; 187} 188#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ 189 190/// GetMainExecutable - Return the path to the main executable, given the 191/// value of argv[0] from program startup. 192std::string getMainExecutable(const char *argv0, void *MainAddr) { 193#if defined(__APPLE__) 194 // On OS X the executable path is saved to the stack by dyld. Reading it 195 // from there is much faster than calling dladdr, especially for large 196 // binaries with symbols. 197 char exe_path[PATH_MAX]; 198 uint32_t size = sizeof(exe_path); 199 if (_NSGetExecutablePath(exe_path, &size) == 0) { 200 char link_path[PATH_MAX]; 201 if (realpath(exe_path, link_path)) 202 return link_path; 203 } 204#elif defined(__FreeBSD__) 205 // On FreeBSD if the exec path specified in ELF auxiliary vectors is 206 // preferred, if available. /proc/curproc/file and the KERN_PROC_PATHNAME 207 // sysctl may not return the desired path if there are multiple hardlinks 208 // to the file. 209 char exe_path[PATH_MAX]; 210#if __FreeBSD_version >= 1300057 211 if (elf_aux_info(AT_EXECPATH, exe_path, sizeof(exe_path)) == 0) 212 return exe_path; 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 (; *(uintptr_t *)p != AT_NULL; p++) { 222 if (*(uintptr_t *)p++ == AT_EXECPATH) 223 return *p; 224 } 225#endif 226 // Fall back to argv[0] if auxiliary vectors are not available. 227 if (getprogpath(exe_path, argv0) != NULL) 228 return exe_path; 229#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__minix) || \ 230 defined(__DragonFly__) || defined(__FreeBSD_kernel__) || defined(_AIX) 231 const char *curproc = "/proc/curproc/file"; 232 char exe_path[PATH_MAX]; 233 if (sys::fs::exists(curproc)) { 234 ssize_t len = readlink(curproc, exe_path, sizeof(exe_path)); 235 if (len > 0) { 236 // Null terminate the string for realpath. readlink never null 237 // terminates its output. 238 len = std::min(len, ssize_t(sizeof(exe_path) - 1)); 239 exe_path[len] = '\0'; 240 return exe_path; 241 } 242 } 243 // If we don't have procfs mounted, fall back to argv[0] 244 if (getprogpath(exe_path, argv0) != NULL) 245 return exe_path; 246#elif defined(__linux__) || defined(__CYGWIN__) || defined(__gnu_hurd__) 247 char exe_path[PATH_MAX]; 248 const char *aPath = "/proc/self/exe"; 249 if (sys::fs::exists(aPath)) { 250 // /proc is not always mounted under Linux (chroot for example). 251 ssize_t len = readlink(aPath, exe_path, sizeof(exe_path)); 252 if (len < 0) 253 return ""; 254 255 // Null terminate the string for realpath. readlink never null 256 // terminates its output. 257 len = std::min(len, ssize_t(sizeof(exe_path) - 1)); 258 exe_path[len] = '\0'; 259 260 // On Linux, /proc/self/exe always looks through symlinks. However, on 261 // GNU/Hurd, /proc/self/exe is a symlink to the path that was used to start 262 // the program, and not the eventual binary file. Therefore, call realpath 263 // so this behaves the same on all platforms. 264#if _POSIX_VERSION >= 200112 || defined(__GLIBC__) 265 if (char *real_path = realpath(exe_path, NULL)) { 266 std::string ret = std::string(real_path); 267 free(real_path); 268 return ret; 269 } 270#else 271 char real_path[PATH_MAX]; 272 if (realpath(exe_path, real_path)) 273 return std::string(real_path); 274#endif 275 } 276 // Fall back to the classical detection. 277 if (getprogpath(exe_path, argv0)) 278 return exe_path; 279#elif defined(__MVS__) 280 int token = 0; 281 W_PSPROC buf; 282 char exe_path[PS_PATHBLEN]; 283 pid_t pid = getpid(); 284 285 memset(&buf, 0, sizeof(buf)); 286 buf.ps_pathptr = exe_path; 287 buf.ps_pathlen = sizeof(exe_path); 288 289 while (true) { 290 if ((token = w_getpsent(token, &buf, sizeof(buf))) <= 0) 291 break; 292 if (buf.ps_pid != pid) 293 continue; 294 char real_path[PATH_MAX]; 295 if (realpath(exe_path, real_path)) 296 return std::string(real_path); 297 break; // Found entry, but realpath failed. 298 } 299#elif defined(HAVE_DLFCN_H) && defined(HAVE_DLADDR) 300 // Use dladdr to get executable path if available. 301 Dl_info DLInfo; 302 int err = dladdr(MainAddr, &DLInfo); 303 if (err == 0) 304 return ""; 305 306 // If the filename is a symlink, we need to resolve and return the location of 307 // the actual executable. 308 char link_path[PATH_MAX]; 309 if (realpath(DLInfo.dli_fname, link_path)) 310 return link_path; 311#else 312#error GetMainExecutable is not implemented on this host yet. 313#endif 314 return ""; 315} 316 317TimePoint<> basic_file_status::getLastAccessedTime() const { 318 return toTimePoint(fs_st_atime, fs_st_atime_nsec); 319} 320 321TimePoint<> basic_file_status::getLastModificationTime() const { 322 return toTimePoint(fs_st_mtime, fs_st_mtime_nsec); 323} 324 325UniqueID file_status::getUniqueID() const { 326 return UniqueID(fs_st_dev, fs_st_ino); 327} 328 329uint32_t file_status::getLinkCount() const { 330 return fs_st_nlinks; 331} 332 333ErrorOr<space_info> disk_space(const Twine &Path) { 334 struct STATVFS Vfs; 335 if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) 336 return std::error_code(errno, std::generic_category()); 337 auto FrSize = STATVFS_F_FRSIZE(Vfs); 338 space_info SpaceInfo; 339 SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize; 340 SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize; 341 SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize; 342 return SpaceInfo; 343} 344 345std::error_code current_path(SmallVectorImpl<char> &result) { 346 result.clear(); 347 348 const char *pwd = ::getenv("PWD"); 349 llvm::sys::fs::file_status PWDStatus, DotStatus; 350 if (pwd && llvm::sys::path::is_absolute(pwd) && 351 !llvm::sys::fs::status(pwd, PWDStatus) && 352 !llvm::sys::fs::status(".", DotStatus) && 353 PWDStatus.getUniqueID() == DotStatus.getUniqueID()) { 354 result.append(pwd, pwd + strlen(pwd)); 355 return std::error_code(); 356 } 357 358 result.reserve(PATH_MAX); 359 360 while (true) { 361 if (::getcwd(result.data(), result.capacity()) == nullptr) { 362 // See if there was a real error. 363 if (errno != ENOMEM) 364 return std::error_code(errno, std::generic_category()); 365 // Otherwise there just wasn't enough space. 366 result.reserve(result.capacity() * 2); 367 } else 368 break; 369 } 370 371 result.set_size(strlen(result.data())); 372 return std::error_code(); 373} 374 375std::error_code set_current_path(const Twine &path) { 376 SmallString<128> path_storage; 377 StringRef p = path.toNullTerminatedStringRef(path_storage); 378 379 if (::chdir(p.begin()) == -1) 380 return std::error_code(errno, std::generic_category()); 381 382 return std::error_code(); 383} 384 385std::error_code create_directory(const Twine &path, bool IgnoreExisting, 386 perms Perms) { 387 SmallString<128> path_storage; 388 StringRef p = path.toNullTerminatedStringRef(path_storage); 389 390 if (::mkdir(p.begin(), Perms) == -1) { 391 if (errno != EEXIST || !IgnoreExisting) 392 return std::error_code(errno, std::generic_category()); 393 } 394 395 return std::error_code(); 396} 397 398// Note that we are using symbolic link because hard links are not supported by 399// all filesystems (SMB doesn't). 400std::error_code create_link(const Twine &to, const Twine &from) { 401 // Get arguments. 402 SmallString<128> from_storage; 403 SmallString<128> to_storage; 404 StringRef f = from.toNullTerminatedStringRef(from_storage); 405 StringRef t = to.toNullTerminatedStringRef(to_storage); 406 407 if (::symlink(t.begin(), f.begin()) == -1) 408 return std::error_code(errno, std::generic_category()); 409 410 return std::error_code(); 411} 412 413std::error_code create_hard_link(const Twine &to, const Twine &from) { 414 // Get arguments. 415 SmallString<128> from_storage; 416 SmallString<128> to_storage; 417 StringRef f = from.toNullTerminatedStringRef(from_storage); 418 StringRef t = to.toNullTerminatedStringRef(to_storage); 419 420 if (::link(t.begin(), f.begin()) == -1) 421 return std::error_code(errno, std::generic_category()); 422 423 return std::error_code(); 424} 425 426std::error_code remove(const Twine &path, bool IgnoreNonExisting) { 427 SmallString<128> path_storage; 428 StringRef p = path.toNullTerminatedStringRef(path_storage); 429 430 struct stat buf; 431 if (lstat(p.begin(), &buf) != 0) { 432 if (errno != ENOENT || !IgnoreNonExisting) 433 return std::error_code(errno, std::generic_category()); 434 return std::error_code(); 435 } 436 437 // Note: this check catches strange situations. In all cases, LLVM should 438 // only be involved in the creation and deletion of regular files. This 439 // check ensures that what we're trying to erase is a regular file. It 440 // effectively prevents LLVM from erasing things like /dev/null, any block 441 // special file, or other things that aren't "regular" files. 442 if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode)) 443 return make_error_code(errc::operation_not_permitted); 444 445 if (::remove(p.begin()) == -1) { 446 if (errno != ENOENT || !IgnoreNonExisting) 447 return std::error_code(errno, std::generic_category()); 448 } 449 450 return std::error_code(); 451} 452 453static bool is_local_impl(struct STATVFS &Vfs) { 454#if defined(__linux__) || defined(__GNU__) 455#ifndef NFS_SUPER_MAGIC 456#define NFS_SUPER_MAGIC 0x6969 457#endif 458#ifndef SMB_SUPER_MAGIC 459#define SMB_SUPER_MAGIC 0x517B 460#endif 461#ifndef CIFS_MAGIC_NUMBER 462#define CIFS_MAGIC_NUMBER 0xFF534D42 463#endif 464#ifdef __GNU__ 465 switch ((uint32_t)Vfs.__f_type) { 466#else 467 switch ((uint32_t)Vfs.f_type) { 468#endif 469 case NFS_SUPER_MAGIC: 470 case SMB_SUPER_MAGIC: 471 case CIFS_MAGIC_NUMBER: 472 return false; 473 default: 474 return true; 475 } 476#elif defined(__CYGWIN__) 477 // Cygwin doesn't expose this information; would need to use Win32 API. 478 return false; 479#elif defined(__Fuchsia__) 480 // Fuchsia doesn't yet support remote filesystem mounts. 481 return true; 482#elif defined(__EMSCRIPTEN__) 483 // Emscripten doesn't currently support remote filesystem mounts. 484 return true; 485#elif defined(__HAIKU__) 486 // Haiku doesn't expose this information. 487 return false; 488#elif defined(__sun) 489 // statvfs::f_basetype contains a null-terminated FSType name of the mounted target 490 StringRef fstype(Vfs.f_basetype); 491 // NFS is the only non-local fstype?? 492 return !fstype.equals("nfs"); 493#elif defined(_AIX) 494 // Call mntctl; try more than twice in case of timing issues with a concurrent 495 // mount. 496 int Ret; 497 size_t BufSize = 2048u; 498 std::unique_ptr<char[]> Buf; 499 int Tries = 3; 500 while (Tries--) { 501 Buf = std::make_unique<char[]>(BufSize); 502 Ret = mntctl(MCTL_QUERY, BufSize, Buf.get()); 503 if (Ret != 0) 504 break; 505 BufSize = *reinterpret_cast<unsigned int *>(Buf.get()); 506 Buf.reset(); 507 } 508 509 if (Ret == -1) 510 // There was an error; "remote" is the conservative answer. 511 return false; 512 513 // Look for the correct vmount entry. 514 char *CurObjPtr = Buf.get(); 515 while (Ret--) { 516 struct vmount *Vp = reinterpret_cast<struct vmount *>(CurObjPtr); 517 static_assert(sizeof(Vfs.f_fsid) == sizeof(Vp->vmt_fsid), 518 "fsid length mismatch"); 519 if (memcmp(&Vfs.f_fsid, &Vp->vmt_fsid, sizeof Vfs.f_fsid) == 0) 520 return (Vp->vmt_flags & MNT_REMOTE) == 0; 521 522 CurObjPtr += Vp->vmt_length; 523 } 524 525 // vmount entry not found; "remote" is the conservative answer. 526 return false; 527#elif defined(__MVS__) 528 // The file system can have an arbitrary structure on z/OS; must go with the 529 // conservative answer. 530 return false; 531#else 532 return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL); 533#endif 534} 535 536std::error_code is_local(const Twine &Path, bool &Result) { 537 struct STATVFS Vfs; 538 if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) 539 return std::error_code(errno, std::generic_category()); 540 541 Result = is_local_impl(Vfs); 542 return std::error_code(); 543} 544 545std::error_code is_local(int FD, bool &Result) { 546 struct STATVFS Vfs; 547 if (::FSTATVFS(FD, &Vfs)) 548 return std::error_code(errno, std::generic_category()); 549 550 Result = is_local_impl(Vfs); 551 return std::error_code(); 552} 553 554std::error_code rename(const Twine &from, const Twine &to) { 555 // Get arguments. 556 SmallString<128> from_storage; 557 SmallString<128> to_storage; 558 StringRef f = from.toNullTerminatedStringRef(from_storage); 559 StringRef t = to.toNullTerminatedStringRef(to_storage); 560 561 if (::rename(f.begin(), t.begin()) == -1) 562 return std::error_code(errno, std::generic_category()); 563 564 return std::error_code(); 565} 566 567std::error_code resize_file(int FD, uint64_t Size) { 568#if defined(HAVE_POSIX_FALLOCATE) 569 // If we have posix_fallocate use it. Unlike ftruncate it always allocates 570 // space, so we get an error if the disk is full. 571 if (int Err = ::posix_fallocate(FD, 0, Size)) { 572#ifdef _AIX 573 constexpr int NotSupportedError = ENOTSUP; 574#else 575 constexpr int NotSupportedError = EOPNOTSUPP; 576#endif 577 if (Err != EINVAL && Err != NotSupportedError) 578 return std::error_code(Err, std::generic_category()); 579 } 580#endif 581 // Use ftruncate as a fallback. It may or may not allocate space. At least on 582 // OS X with HFS+ it does. 583 if (::ftruncate(FD, Size) == -1) 584 return std::error_code(errno, std::generic_category()); 585 586 return std::error_code(); 587} 588 589static int convertAccessMode(AccessMode Mode) { 590 switch (Mode) { 591 case AccessMode::Exist: 592 return F_OK; 593 case AccessMode::Write: 594 return W_OK; 595 case AccessMode::Execute: 596 return R_OK | X_OK; // scripts also need R_OK. 597 } 598 llvm_unreachable("invalid enum"); 599} 600 601std::error_code access(const Twine &Path, AccessMode Mode) { 602 SmallString<128> PathStorage; 603 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 604 605 if (::access(P.begin(), convertAccessMode(Mode)) == -1) 606 return std::error_code(errno, std::generic_category()); 607 608 if (Mode == AccessMode::Execute) { 609 // Don't say that directories are executable. 610 struct stat buf; 611 if (0 != stat(P.begin(), &buf)) 612 return errc::permission_denied; 613 if (!S_ISREG(buf.st_mode)) 614 return errc::permission_denied; 615 } 616 617 return std::error_code(); 618} 619 620bool can_execute(const Twine &Path) { 621 return !access(Path, AccessMode::Execute); 622} 623 624bool equivalent(file_status A, file_status B) { 625 assert(status_known(A) && status_known(B)); 626 return A.fs_st_dev == B.fs_st_dev && 627 A.fs_st_ino == B.fs_st_ino; 628} 629 630std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { 631 file_status fsA, fsB; 632 if (std::error_code ec = status(A, fsA)) 633 return ec; 634 if (std::error_code ec = status(B, fsB)) 635 return ec; 636 result = equivalent(fsA, fsB); 637 return std::error_code(); 638} 639 640static void expandTildeExpr(SmallVectorImpl<char> &Path) { 641 StringRef PathStr(Path.begin(), Path.size()); 642 if (PathStr.empty() || !PathStr.startswith("~")) 643 return; 644 645 PathStr = PathStr.drop_front(); 646 StringRef Expr = 647 PathStr.take_until([](char c) { return path::is_separator(c); }); 648 StringRef Remainder = PathStr.substr(Expr.size() + 1); 649 SmallString<128> Storage; 650 if (Expr.empty()) { 651 // This is just ~/..., resolve it to the current user's home dir. 652 if (!path::home_directory(Storage)) { 653 // For some reason we couldn't get the home directory. Just exit. 654 return; 655 } 656 657 // Overwrite the first character and insert the rest. 658 Path[0] = Storage[0]; 659 Path.insert(Path.begin() + 1, Storage.begin() + 1, Storage.end()); 660 return; 661 } 662 663 // This is a string of the form ~username/, look up this user's entry in the 664 // password database. 665 struct passwd *Entry = nullptr; 666 std::string User = Expr.str(); 667 Entry = ::getpwnam(User.c_str()); 668 669 if (!Entry) { 670 // Unable to look up the entry, just return back the original path. 671 return; 672 } 673 674 Storage = Remainder; 675 Path.clear(); 676 Path.append(Entry->pw_dir, Entry->pw_dir + strlen(Entry->pw_dir)); 677 llvm::sys::path::append(Path, Storage); 678} 679 680 681void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) { 682 dest.clear(); 683 if (path.isTriviallyEmpty()) 684 return; 685 686 path.toVector(dest); 687 expandTildeExpr(dest); 688} 689 690static file_type typeForMode(mode_t Mode) { 691 if (S_ISDIR(Mode)) 692 return file_type::directory_file; 693 else if (S_ISREG(Mode)) 694 return file_type::regular_file; 695 else if (S_ISBLK(Mode)) 696 return file_type::block_file; 697 else if (S_ISCHR(Mode)) 698 return file_type::character_file; 699 else if (S_ISFIFO(Mode)) 700 return file_type::fifo_file; 701 else if (S_ISSOCK(Mode)) 702 return file_type::socket_file; 703 else if (S_ISLNK(Mode)) 704 return file_type::symlink_file; 705 return file_type::type_unknown; 706} 707 708static std::error_code fillStatus(int StatRet, const struct stat &Status, 709 file_status &Result) { 710 if (StatRet != 0) { 711 std::error_code EC(errno, std::generic_category()); 712 if (EC == errc::no_such_file_or_directory) 713 Result = file_status(file_type::file_not_found); 714 else 715 Result = file_status(file_type::status_error); 716 return EC; 717 } 718 719 uint32_t atime_nsec, mtime_nsec; 720#if defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) 721 atime_nsec = Status.st_atimespec.tv_nsec; 722 mtime_nsec = Status.st_mtimespec.tv_nsec; 723#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) 724 atime_nsec = Status.st_atim.tv_nsec; 725 mtime_nsec = Status.st_mtim.tv_nsec; 726#else 727 atime_nsec = mtime_nsec = 0; 728#endif 729 730 perms Perms = static_cast<perms>(Status.st_mode) & all_perms; 731 Result = file_status(typeForMode(Status.st_mode), Perms, Status.st_dev, 732 Status.st_nlink, Status.st_ino, 733 Status.st_atime, atime_nsec, Status.st_mtime, mtime_nsec, 734 Status.st_uid, Status.st_gid, Status.st_size); 735 736 return std::error_code(); 737} 738 739std::error_code status(const Twine &Path, file_status &Result, bool Follow) { 740 SmallString<128> PathStorage; 741 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 742 743 struct stat Status; 744 int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status); 745 return fillStatus(StatRet, Status, Result); 746} 747 748std::error_code status(int FD, file_status &Result) { 749 struct stat Status; 750 int StatRet = ::fstat(FD, &Status); 751 return fillStatus(StatRet, Status, Result); 752} 753 754unsigned getUmask() { 755 // Chose arbitary new mask and reset the umask to the old mask. 756 // umask(2) never fails so ignore the return of the second call. 757 unsigned Mask = ::umask(0); 758 (void) ::umask(Mask); 759 return Mask; 760} 761 762std::error_code setPermissions(const Twine &Path, perms Permissions) { 763 SmallString<128> PathStorage; 764 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 765 766 if (::chmod(P.begin(), Permissions)) 767 return std::error_code(errno, std::generic_category()); 768 return std::error_code(); 769} 770 771std::error_code setPermissions(int FD, perms Permissions) { 772 if (::fchmod(FD, Permissions)) 773 return std::error_code(errno, std::generic_category()); 774 return std::error_code(); 775} 776 777std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, 778 TimePoint<> ModificationTime) { 779#if defined(HAVE_FUTIMENS) 780 timespec Times[2]; 781 Times[0] = sys::toTimeSpec(AccessTime); 782 Times[1] = sys::toTimeSpec(ModificationTime); 783 if (::futimens(FD, Times)) 784 return std::error_code(errno, std::generic_category()); 785 return std::error_code(); 786#elif defined(HAVE_FUTIMES) 787 timeval Times[2]; 788 Times[0] = sys::toTimeVal( 789 std::chrono::time_point_cast<std::chrono::microseconds>(AccessTime)); 790 Times[1] = 791 sys::toTimeVal(std::chrono::time_point_cast<std::chrono::microseconds>( 792 ModificationTime)); 793 if (::futimes(FD, Times)) 794 return std::error_code(errno, std::generic_category()); 795 return std::error_code(); 796#elif defined(__MVS__) 797 attrib_t Attr; 798 memset(&Attr, 0, sizeof(Attr)); 799 Attr.att_atimechg = 1; 800 Attr.att_atime = sys::toTimeT(AccessTime); 801 Attr.att_mtimechg = 1; 802 Attr.att_mtime = sys::toTimeT(ModificationTime); 803 if (::__fchattr(FD, &Attr, sizeof(Attr)) != 0) 804 return std::error_code(errno, std::generic_category()); 805 return std::error_code(); 806#else 807#warning Missing futimes() and futimens() 808 return make_error_code(errc::function_not_supported); 809#endif 810} 811 812std::error_code mapped_file_region::init(int FD, uint64_t Offset, 813 mapmode Mode) { 814 assert(Size != 0); 815 816 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; 817 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); 818#if defined(__APPLE__) 819 //---------------------------------------------------------------------- 820 // Newer versions of MacOSX have a flag that will allow us to read from 821 // binaries whose code signature is invalid without crashing by using 822 // the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media 823 // is mapped we can avoid crashing and return zeroes to any pages we try 824 // to read if the media becomes unavailable by using the 825 // MAP_RESILIENT_MEDIA flag. These flags are only usable when mapping 826 // with PROT_READ, so take care not to specify them otherwise. 827 //---------------------------------------------------------------------- 828 if (Mode == readonly) { 829#if defined(MAP_RESILIENT_CODESIGN) 830 flags |= MAP_RESILIENT_CODESIGN; 831#endif 832#if defined(MAP_RESILIENT_MEDIA) 833 flags |= MAP_RESILIENT_MEDIA; 834#endif 835 } 836#endif // #if defined (__APPLE__) 837 838 Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset); 839 if (Mapping == MAP_FAILED) 840 return std::error_code(errno, std::generic_category()); 841 return std::error_code(); 842} 843 844mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length, 845 uint64_t offset, std::error_code &ec) 846 : Size(length), Mapping(), Mode(mode) { 847 (void)Mode; 848 ec = init(fd, offset, mode); 849 if (ec) 850 Mapping = nullptr; 851} 852 853mapped_file_region::~mapped_file_region() { 854 if (Mapping) 855 ::munmap(Mapping, Size); 856} 857 858size_t mapped_file_region::size() const { 859 assert(Mapping && "Mapping failed but used anyway!"); 860 return Size; 861} 862 863char *mapped_file_region::data() const { 864 assert(Mapping && "Mapping failed but used anyway!"); 865 return reinterpret_cast<char*>(Mapping); 866} 867 868const char *mapped_file_region::const_data() const { 869 assert(Mapping && "Mapping failed but used anyway!"); 870 return reinterpret_cast<const char*>(Mapping); 871} 872 873int mapped_file_region::alignment() { 874 return Process::getPageSizeEstimate(); 875} 876 877std::error_code detail::directory_iterator_construct(detail::DirIterState &it, 878 StringRef path, 879 bool follow_symlinks) { 880 SmallString<128> path_null(path); 881 DIR *directory = ::opendir(path_null.c_str()); 882 if (!directory) 883 return std::error_code(errno, std::generic_category()); 884 885 it.IterationHandle = reinterpret_cast<intptr_t>(directory); 886 // Add something for replace_filename to replace. 887 path::append(path_null, "."); 888 it.CurrentEntry = directory_entry(path_null.str(), follow_symlinks); 889 return directory_iterator_increment(it); 890} 891 892std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { 893 if (it.IterationHandle) 894 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle)); 895 it.IterationHandle = 0; 896 it.CurrentEntry = directory_entry(); 897 return std::error_code(); 898} 899 900static file_type direntType(dirent* Entry) { 901 // Most platforms provide the file type in the dirent: Linux/BSD/Mac. 902 // The DTTOIF macro lets us reuse our status -> type conversion. 903 // Note that while glibc provides a macro to see if this is supported, 904 // _DIRENT_HAVE_D_TYPE, it's not defined on BSD/Mac, so we test for the 905 // d_type-to-mode_t conversion macro instead. 906#if defined(DTTOIF) 907 return typeForMode(DTTOIF(Entry->d_type)); 908#else 909 // Other platforms such as Solaris require a stat() to get the type. 910 return file_type::type_unknown; 911#endif 912} 913 914std::error_code detail::directory_iterator_increment(detail::DirIterState &It) { 915 errno = 0; 916 dirent *CurDir = ::readdir(reinterpret_cast<DIR *>(It.IterationHandle)); 917 if (CurDir == nullptr && errno != 0) { 918 return std::error_code(errno, std::generic_category()); 919 } else if (CurDir != nullptr) { 920 StringRef Name(CurDir->d_name); 921 if ((Name.size() == 1 && Name[0] == '.') || 922 (Name.size() == 2 && Name[0] == '.' && Name[1] == '.')) 923 return directory_iterator_increment(It); 924 It.CurrentEntry.replace_filename(Name, direntType(CurDir)); 925 } else 926 return directory_iterator_destruct(It); 927 928 return std::error_code(); 929} 930 931ErrorOr<basic_file_status> directory_entry::status() const { 932 file_status s; 933 if (auto EC = fs::status(Path, s, FollowSymlinks)) 934 return EC; 935 return s; 936} 937 938#if !defined(F_GETPATH) 939static bool hasProcSelfFD() { 940 // If we have a /proc filesystem mounted, we can quickly establish the 941 // real name of the file with readlink 942 static const bool Result = (::access("/proc/self/fd", R_OK) == 0); 943 return Result; 944} 945#endif 946 947static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags, 948 FileAccess Access) { 949 int Result = 0; 950 if (Access == FA_Read) 951 Result |= O_RDONLY; 952 else if (Access == FA_Write) 953 Result |= O_WRONLY; 954 else if (Access == (FA_Read | FA_Write)) 955 Result |= O_RDWR; 956 957 // This is for compatibility with old code that assumed OF_Append implied 958 // would open an existing file. See Windows/Path.inc for a longer comment. 959 if (Flags & OF_Append) 960 Disp = CD_OpenAlways; 961 962 if (Disp == CD_CreateNew) { 963 Result |= O_CREAT; // Create if it doesn't exist. 964 Result |= O_EXCL; // Fail if it does. 965 } else if (Disp == CD_CreateAlways) { 966 Result |= O_CREAT; // Create if it doesn't exist. 967 Result |= O_TRUNC; // Truncate if it does. 968 } else if (Disp == CD_OpenAlways) { 969 Result |= O_CREAT; // Create if it doesn't exist. 970 } else if (Disp == CD_OpenExisting) { 971 // Nothing special, just don't add O_CREAT and we get these semantics. 972 } 973 974 if (Flags & OF_Append) 975 Result |= O_APPEND; 976 977#ifdef O_CLOEXEC 978 if (!(Flags & OF_ChildInherit)) 979 Result |= O_CLOEXEC; 980#endif 981 982 return Result; 983} 984 985std::error_code openFile(const Twine &Name, int &ResultFD, 986 CreationDisposition Disp, FileAccess Access, 987 OpenFlags Flags, unsigned Mode) { 988 int OpenFlags = nativeOpenFlags(Disp, Flags, Access); 989 990 SmallString<128> Storage; 991 StringRef P = Name.toNullTerminatedStringRef(Storage); 992 // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal 993 // when open is overloaded, such as in Bionic. 994 auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); }; 995 if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0) 996 return std::error_code(errno, std::generic_category()); 997#ifndef O_CLOEXEC 998 if (!(Flags & OF_ChildInherit)) { 999 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC); 1000 (void)r; 1001 assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed"); 1002 } 1003#endif 1004 return std::error_code(); 1005} 1006 1007Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp, 1008 FileAccess Access, OpenFlags Flags, 1009 unsigned Mode) { 1010 1011 int FD; 1012 std::error_code EC = openFile(Name, FD, Disp, Access, Flags, Mode); 1013 if (EC) 1014 return errorCodeToError(EC); 1015 return FD; 1016} 1017 1018std::error_code openFileForRead(const Twine &Name, int &ResultFD, 1019 OpenFlags Flags, 1020 SmallVectorImpl<char> *RealPath) { 1021 std::error_code EC = 1022 openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666); 1023 if (EC) 1024 return EC; 1025 1026 // Attempt to get the real name of the file, if the user asked 1027 if(!RealPath) 1028 return std::error_code(); 1029 RealPath->clear(); 1030#if defined(F_GETPATH) 1031 // When F_GETPATH is availble, it is the quickest way to get 1032 // the real path name. 1033 char Buffer[PATH_MAX]; 1034 if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1) 1035 RealPath->append(Buffer, Buffer + strlen(Buffer)); 1036#else 1037 char Buffer[PATH_MAX]; 1038 if (hasProcSelfFD()) { 1039 char ProcPath[64]; 1040 snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD); 1041 ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer)); 1042 if (CharCount > 0) 1043 RealPath->append(Buffer, Buffer + CharCount); 1044 } else { 1045 SmallString<128> Storage; 1046 StringRef P = Name.toNullTerminatedStringRef(Storage); 1047 1048 // Use ::realpath to get the real path name 1049 if (::realpath(P.begin(), Buffer) != nullptr) 1050 RealPath->append(Buffer, Buffer + strlen(Buffer)); 1051 } 1052#endif 1053 return std::error_code(); 1054} 1055 1056Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags, 1057 SmallVectorImpl<char> *RealPath) { 1058 file_t ResultFD; 1059 std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath); 1060 if (EC) 1061 return errorCodeToError(EC); 1062 return ResultFD; 1063} 1064 1065file_t getStdinHandle() { return 0; } 1066file_t getStdoutHandle() { return 1; } 1067file_t getStderrHandle() { return 2; } 1068 1069Expected<size_t> readNativeFile(file_t FD, MutableArrayRef<char> Buf) { 1070#if defined(__APPLE__) 1071 size_t Size = std::min<size_t>(Buf.size(), INT32_MAX); 1072#else 1073 size_t Size = Buf.size(); 1074#endif 1075 ssize_t NumRead = 1076 sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); 1077 if (ssize_t(NumRead) == -1) 1078 return errorCodeToError(std::error_code(errno, std::generic_category())); 1079 return NumRead; 1080} 1081 1082Expected<size_t> readNativeFileSlice(file_t FD, MutableArrayRef<char> Buf, 1083 uint64_t Offset) { 1084#if defined(__APPLE__) 1085 size_t Size = std::min<size_t>(Buf.size(), INT32_MAX); 1086#else 1087 size_t Size = Buf.size(); 1088#endif 1089#ifdef HAVE_PREAD 1090 ssize_t NumRead = 1091 sys::RetryAfterSignal(-1, ::pread, FD, Buf.data(), Size, Offset); 1092#else 1093 if (lseek(FD, Offset, SEEK_SET) == -1) 1094 return errorCodeToError(std::error_code(errno, std::generic_category())); 1095 ssize_t NumRead = 1096 sys::RetryAfterSignal(-1, ::read, FD, Buf.data(), Size); 1097#endif 1098 if (NumRead == -1) 1099 return errorCodeToError(std::error_code(errno, std::generic_category())); 1100 return NumRead; 1101} 1102 1103std::error_code tryLockFile(int FD, std::chrono::milliseconds Timeout) { 1104 auto Start = std::chrono::steady_clock::now(); 1105 auto End = Start + Timeout; 1106 do { 1107 struct flock Lock; 1108 memset(&Lock, 0, sizeof(Lock)); 1109 Lock.l_type = F_WRLCK; 1110 Lock.l_whence = SEEK_SET; 1111 Lock.l_start = 0; 1112 Lock.l_len = 0; 1113 if (::fcntl(FD, F_SETLK, &Lock) != -1) 1114 return std::error_code(); 1115 int Error = errno; 1116 if (Error != EACCES && Error != EAGAIN) 1117 return std::error_code(Error, std::generic_category()); 1118 usleep(1000); 1119 } while (std::chrono::steady_clock::now() < End); 1120 return make_error_code(errc::no_lock_available); 1121} 1122 1123std::error_code lockFile(int FD) { 1124 struct flock Lock; 1125 memset(&Lock, 0, sizeof(Lock)); 1126 Lock.l_type = F_WRLCK; 1127 Lock.l_whence = SEEK_SET; 1128 Lock.l_start = 0; 1129 Lock.l_len = 0; 1130 if (::fcntl(FD, F_SETLKW, &Lock) != -1) 1131 return std::error_code(); 1132 int Error = errno; 1133 return std::error_code(Error, std::generic_category()); 1134} 1135 1136std::error_code unlockFile(int FD) { 1137 struct flock Lock; 1138 Lock.l_type = F_UNLCK; 1139 Lock.l_whence = SEEK_SET; 1140 Lock.l_start = 0; 1141 Lock.l_len = 0; 1142 if (::fcntl(FD, F_SETLK, &Lock) != -1) 1143 return std::error_code(); 1144 return std::error_code(errno, std::generic_category()); 1145} 1146 1147std::error_code closeFile(file_t &F) { 1148 file_t TmpF = F; 1149 F = kInvalidFile; 1150 return Process::SafelyCloseFileDescriptor(TmpF); 1151} 1152 1153template <typename T> 1154static std::error_code remove_directories_impl(const T &Entry, 1155 bool IgnoreErrors) { 1156 std::error_code EC; 1157 directory_iterator Begin(Entry, EC, false); 1158 directory_iterator End; 1159 while (Begin != End) { 1160 auto &Item = *Begin; 1161 ErrorOr<basic_file_status> st = Item.status(); 1162 if (!st && !IgnoreErrors) 1163 return st.getError(); 1164 1165 if (is_directory(*st)) { 1166 EC = remove_directories_impl(Item, IgnoreErrors); 1167 if (EC && !IgnoreErrors) 1168 return EC; 1169 } 1170 1171 EC = fs::remove(Item.path(), true); 1172 if (EC && !IgnoreErrors) 1173 return EC; 1174 1175 Begin.increment(EC); 1176 if (EC && !IgnoreErrors) 1177 return EC; 1178 } 1179 return std::error_code(); 1180} 1181 1182std::error_code remove_directories(const Twine &path, bool IgnoreErrors) { 1183 auto EC = remove_directories_impl(path, IgnoreErrors); 1184 if (EC && !IgnoreErrors) 1185 return EC; 1186 EC = fs::remove(path, true); 1187 if (EC && !IgnoreErrors) 1188 return EC; 1189 return std::error_code(); 1190} 1191 1192std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest, 1193 bool expand_tilde) { 1194 dest.clear(); 1195 if (path.isTriviallyEmpty()) 1196 return std::error_code(); 1197 1198 if (expand_tilde) { 1199 SmallString<128> Storage; 1200 path.toVector(Storage); 1201 expandTildeExpr(Storage); 1202 return real_path(Storage, dest, false); 1203 } 1204 1205 SmallString<128> Storage; 1206 StringRef P = path.toNullTerminatedStringRef(Storage); 1207 char Buffer[PATH_MAX]; 1208 if (::realpath(P.begin(), Buffer) == nullptr) 1209 return std::error_code(errno, std::generic_category()); 1210 dest.append(Buffer, Buffer + strlen(Buffer)); 1211 return std::error_code(); 1212} 1213 1214} // end namespace fs 1215 1216namespace path { 1217 1218bool home_directory(SmallVectorImpl<char> &result) { 1219 char *RequestedDir = getenv("HOME"); 1220 if (!RequestedDir) { 1221 struct passwd *pw = getpwuid(getuid()); 1222 if (pw && pw->pw_dir) 1223 RequestedDir = pw->pw_dir; 1224 } 1225 if (!RequestedDir) 1226 return false; 1227 1228 result.clear(); 1229 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1230 return true; 1231} 1232 1233static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) { 1234 #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) 1235 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. 1236 // macros defined in <unistd.h> on darwin >= 9 1237 int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR 1238 : _CS_DARWIN_USER_CACHE_DIR; 1239 size_t ConfLen = confstr(ConfName, nullptr, 0); 1240 if (ConfLen > 0) { 1241 do { 1242 Result.resize(ConfLen); 1243 ConfLen = confstr(ConfName, Result.data(), Result.size()); 1244 } while (ConfLen > 0 && ConfLen != Result.size()); 1245 1246 if (ConfLen > 0) { 1247 assert(Result.back() == 0); 1248 Result.pop_back(); 1249 return true; 1250 } 1251 1252 Result.clear(); 1253 } 1254 #endif 1255 return false; 1256} 1257 1258bool user_config_directory(SmallVectorImpl<char> &result) { 1259#ifdef __APPLE__ 1260 // Mac: ~/Library/Preferences/ 1261 if (home_directory(result)) { 1262 append(result, "Library", "Preferences"); 1263 return true; 1264 } 1265#else 1266 // XDG_CONFIG_HOME as defined in the XDG Base Directory Specification: 1267 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html 1268 if (const char *RequestedDir = getenv("XDG_CONFIG_HOME")) { 1269 result.clear(); 1270 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1271 return true; 1272 } 1273#endif 1274 // Fallback: ~/.config 1275 if (!home_directory(result)) { 1276 return false; 1277 } 1278 append(result, ".config"); 1279 return true; 1280} 1281 1282bool cache_directory(SmallVectorImpl<char> &result) { 1283#ifdef __APPLE__ 1284 if (getDarwinConfDir(false/*tempDir*/, result)) { 1285 return true; 1286 } 1287#else 1288 // XDG_CACHE_HOME as defined in the XDG Base Directory Specification: 1289 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html 1290 if (const char *RequestedDir = getenv("XDG_CACHE_HOME")) { 1291 result.clear(); 1292 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1293 return true; 1294 } 1295#endif 1296 if (!home_directory(result)) { 1297 return false; 1298 } 1299 append(result, ".cache"); 1300 return true; 1301} 1302 1303static const char *getEnvTempDir() { 1304 // Check whether the temporary directory is specified by an environment 1305 // variable. 1306 const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; 1307 for (const char *Env : EnvironmentVariables) { 1308 if (const char *Dir = std::getenv(Env)) 1309 return Dir; 1310 } 1311 1312 return nullptr; 1313} 1314 1315static const char *getDefaultTempDir(bool ErasedOnReboot) { 1316#ifdef P_tmpdir 1317 if ((bool)P_tmpdir) 1318 return P_tmpdir; 1319#endif 1320 1321 if (ErasedOnReboot) 1322 return "/tmp"; 1323 return "/var/tmp"; 1324} 1325 1326void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { 1327 Result.clear(); 1328 1329 if (ErasedOnReboot) { 1330 // There is no env variable for the cache directory. 1331 if (const char *RequestedDir = getEnvTempDir()) { 1332 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1333 return; 1334 } 1335 } 1336 1337 if (getDarwinConfDir(ErasedOnReboot, Result)) 1338 return; 1339 1340 const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); 1341 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1342} 1343 1344} // end namespace path 1345 1346namespace fs { 1347 1348#ifdef __APPLE__ 1349/// This implementation tries to perform an APFS CoW clone of the file, 1350/// which can be much faster and uses less space. 1351/// Unfortunately fcopyfile(3) does not support COPYFILE_CLONE, so the 1352/// file descriptor variant of this function still uses the default 1353/// implementation. 1354std::error_code copy_file(const Twine &From, const Twine &To) { 1355 uint32_t Flag = COPYFILE_DATA; 1356#if __has_builtin(__builtin_available) && defined(COPYFILE_CLONE) 1357 if (__builtin_available(macos 10.12, *)) { 1358 bool IsSymlink; 1359 if (std::error_code Error = is_symlink_file(From, IsSymlink)) 1360 return Error; 1361 // COPYFILE_CLONE clones the symlink instead of following it 1362 // and returns EEXISTS if the target file already exists. 1363 if (!IsSymlink && !exists(To)) 1364 Flag = COPYFILE_CLONE; 1365 } 1366#endif 1367 int Status = 1368 copyfile(From.str().c_str(), To.str().c_str(), /* State */ NULL, Flag); 1369 1370 if (Status == 0) 1371 return std::error_code(); 1372 return std::error_code(errno, std::generic_category()); 1373} 1374#endif // __APPLE__ 1375 1376} // end namespace fs 1377 1378} // end namespace sys 1379} // end namespace llvm 1380