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 37#ifdef __APPLE__ 38#include <mach-o/dyld.h> 39#include <sys/attr.h> 40#elif defined(__DragonFly__) 41#include <sys/mount.h> 42#endif 43 44// Both stdio.h and cstdio are included via different paths and 45// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros 46// either. 47#undef ferror 48#undef feof 49 50// For GNU Hurd 51#if defined(__GNU__) && !defined(PATH_MAX) 52# define PATH_MAX 4096 53# define MAXPATHLEN 4096 54#endif 55 56#include <sys/types.h> 57#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__FreeBSD__) && \ 58 !defined(__linux__) && !defined(__FreeBSD_kernel__) && !defined(_AIX) 59#include <sys/statvfs.h> 60#define STATVFS statvfs 61#define FSTATVFS fstatvfs 62#define STATVFS_F_FRSIZE(vfs) vfs.f_frsize 63#else 64#if defined(__OpenBSD__) || defined(__FreeBSD__) 65#include <sys/mount.h> 66#include <sys/param.h> 67#elif defined(__linux__) 68#if defined(HAVE_LINUX_MAGIC_H) 69#include <linux/magic.h> 70#else 71#if defined(HAVE_LINUX_NFS_FS_H) 72#include <linux/nfs_fs.h> 73#endif 74#if defined(HAVE_LINUX_SMB_H) 75#include <linux/smb.h> 76#endif 77#endif 78#include <sys/vfs.h> 79#elif defined(_AIX) 80#include <sys/statfs.h> 81 82// <sys/vmount.h> depends on `uint` to be a typedef from <sys/types.h> to 83// `uint_t`; however, <sys/types.h> does not always declare `uint`. We provide 84// the typedef prior to including <sys/vmount.h> to work around this issue. 85typedef uint_t uint; 86#include <sys/vmount.h> 87#else 88#include <sys/mount.h> 89#endif 90#define STATVFS statfs 91#define FSTATVFS fstatfs 92#define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize) 93#endif 94 95#if defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__) 96#define STATVFS_F_FLAG(vfs) (vfs).f_flag 97#else 98#define STATVFS_F_FLAG(vfs) (vfs).f_flags 99#endif 100 101using namespace llvm; 102 103namespace llvm { 104namespace sys { 105namespace fs { 106 107const file_t kInvalidFile = -1; 108 109#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ 110 defined(__minix) || defined(__FreeBSD_kernel__) || defined(__linux__) || \ 111 defined(__CYGWIN__) || defined(__DragonFly__) || defined(_AIX) || defined(__GNU__) 112static int 113test_dir(char ret[PATH_MAX], const char *dir, const char *bin) 114{ 115 struct stat sb; 116 char fullpath[PATH_MAX]; 117 118 int chars = snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); 119 // We cannot write PATH_MAX characters because the string will be terminated 120 // with a null character. Fail if truncation happened. 121 if (chars >= PATH_MAX) 122 return 1; 123 if (!realpath(fullpath, ret)) 124 return 1; 125 if (stat(fullpath, &sb) != 0) 126 return 1; 127 128 return 0; 129} 130 131static char * 132getprogpath(char ret[PATH_MAX], const char *bin) 133{ 134 char *pv, *s, *t; 135 136 /* First approach: absolute path. */ 137 if (bin[0] == '/') { 138 if (test_dir(ret, "/", bin) == 0) 139 return ret; 140 return nullptr; 141 } 142 143 /* Second approach: relative path. */ 144 if (strchr(bin, '/')) { 145 char cwd[PATH_MAX]; 146 if (!getcwd(cwd, PATH_MAX)) 147 return nullptr; 148 if (test_dir(ret, cwd, bin) == 0) 149 return ret; 150 return nullptr; 151 } 152 153 /* Third approach: $PATH */ 154 if ((pv = getenv("PATH")) == nullptr) 155 return nullptr; 156 s = pv = strdup(pv); 157 if (!pv) 158 return nullptr; 159 while ((t = strsep(&s, ":")) != nullptr) { 160 if (test_dir(ret, t, bin) == 0) { 161 free(pv); 162 return ret; 163 } 164 } 165 free(pv); 166 return nullptr; 167} 168#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ 169 170/// GetMainExecutable - Return the path to the main executable, given the 171/// value of argv[0] from program startup. 172std::string getMainExecutable(const char *argv0, void *MainAddr) { 173#if defined(__APPLE__) 174 // On OS X the executable path is saved to the stack by dyld. Reading it 175 // from there is much faster than calling dladdr, especially for large 176 // binaries with symbols. 177 char exe_path[MAXPATHLEN]; 178 uint32_t size = sizeof(exe_path); 179 if (_NSGetExecutablePath(exe_path, &size) == 0) { 180 char link_path[MAXPATHLEN]; 181 if (realpath(exe_path, link_path)) 182 return link_path; 183 } 184#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || \ 185 defined(__minix) || defined(__DragonFly__) || \ 186 defined(__FreeBSD_kernel__) || defined(_AIX) 187 char exe_path[PATH_MAX]; 188 189 if (getprogpath(exe_path, argv0) != NULL) 190 return exe_path; 191#elif defined(__linux__) || defined(__CYGWIN__) 192 char exe_path[MAXPATHLEN]; 193 StringRef aPath("/proc/self/exe"); 194 if (sys::fs::exists(aPath)) { 195 // /proc is not always mounted under Linux (chroot for example). 196 ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); 197 if (len < 0) 198 return ""; 199 200 // Null terminate the string for realpath. readlink never null 201 // terminates its output. 202 len = std::min(len, ssize_t(sizeof(exe_path) - 1)); 203 exe_path[len] = '\0'; 204 205 // On Linux, /proc/self/exe always looks through symlinks. However, on 206 // GNU/Hurd, /proc/self/exe is a symlink to the path that was used to start 207 // the program, and not the eventual binary file. Therefore, call realpath 208 // so this behaves the same on all platforms. 209#if _POSIX_VERSION >= 200112 || defined(__GLIBC__) 210 char *real_path = realpath(exe_path, NULL); 211 std::string ret = std::string(real_path); 212 free(real_path); 213 return ret; 214#else 215 char real_path[MAXPATHLEN]; 216 realpath(exe_path, real_path); 217 return std::string(real_path); 218#endif 219 } else { 220 // Fall back to the classical detection. 221 if (getprogpath(exe_path, argv0)) 222 return exe_path; 223 } 224#elif defined(HAVE_DLFCN_H) && defined(HAVE_DLADDR) 225 // Use dladdr to get executable path if available. 226 Dl_info DLInfo; 227 int err = dladdr(MainAddr, &DLInfo); 228 if (err == 0) 229 return ""; 230 231 // If the filename is a symlink, we need to resolve and return the location of 232 // the actual executable. 233 char link_path[MAXPATHLEN]; 234 if (realpath(DLInfo.dli_fname, link_path)) 235 return link_path; 236#else 237#error GetMainExecutable is not implemented on this host yet. 238#endif 239 return ""; 240} 241 242TimePoint<> basic_file_status::getLastAccessedTime() const { 243 return toTimePoint(fs_st_atime, fs_st_atime_nsec); 244} 245 246TimePoint<> basic_file_status::getLastModificationTime() const { 247 return toTimePoint(fs_st_mtime, fs_st_mtime_nsec); 248} 249 250UniqueID file_status::getUniqueID() const { 251 return UniqueID(fs_st_dev, fs_st_ino); 252} 253 254uint32_t file_status::getLinkCount() const { 255 return fs_st_nlinks; 256} 257 258ErrorOr<space_info> disk_space(const Twine &Path) { 259 struct STATVFS Vfs; 260 if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) 261 return std::error_code(errno, std::generic_category()); 262 auto FrSize = STATVFS_F_FRSIZE(Vfs); 263 space_info SpaceInfo; 264 SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize; 265 SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize; 266 SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize; 267 return SpaceInfo; 268} 269 270std::error_code current_path(SmallVectorImpl<char> &result) { 271 result.clear(); 272 273 const char *pwd = ::getenv("PWD"); 274 llvm::sys::fs::file_status PWDStatus, DotStatus; 275 if (pwd && llvm::sys::path::is_absolute(pwd) && 276 !llvm::sys::fs::status(pwd, PWDStatus) && 277 !llvm::sys::fs::status(".", DotStatus) && 278 PWDStatus.getUniqueID() == DotStatus.getUniqueID()) { 279 result.append(pwd, pwd + strlen(pwd)); 280 return std::error_code(); 281 } 282 283#ifdef MAXPATHLEN 284 result.reserve(MAXPATHLEN); 285#else 286// For GNU Hurd 287 result.reserve(1024); 288#endif 289 290 while (true) { 291 if (::getcwd(result.data(), result.capacity()) == nullptr) { 292 // See if there was a real error. 293 if (errno != ENOMEM) 294 return std::error_code(errno, std::generic_category()); 295 // Otherwise there just wasn't enough space. 296 result.reserve(result.capacity() * 2); 297 } else 298 break; 299 } 300 301 result.set_size(strlen(result.data())); 302 return std::error_code(); 303} 304 305std::error_code set_current_path(const Twine &path) { 306 SmallString<128> path_storage; 307 StringRef p = path.toNullTerminatedStringRef(path_storage); 308 309 if (::chdir(p.begin()) == -1) 310 return std::error_code(errno, std::generic_category()); 311 312 return std::error_code(); 313} 314 315std::error_code create_directory(const Twine &path, bool IgnoreExisting, 316 perms Perms) { 317 SmallString<128> path_storage; 318 StringRef p = path.toNullTerminatedStringRef(path_storage); 319 320 if (::mkdir(p.begin(), Perms) == -1) { 321 if (errno != EEXIST || !IgnoreExisting) 322 return std::error_code(errno, std::generic_category()); 323 } 324 325 return std::error_code(); 326} 327 328// Note that we are using symbolic link because hard links are not supported by 329// all filesystems (SMB doesn't). 330std::error_code create_link(const Twine &to, const Twine &from) { 331 // Get arguments. 332 SmallString<128> from_storage; 333 SmallString<128> to_storage; 334 StringRef f = from.toNullTerminatedStringRef(from_storage); 335 StringRef t = to.toNullTerminatedStringRef(to_storage); 336 337 if (::symlink(t.begin(), f.begin()) == -1) 338 return std::error_code(errno, std::generic_category()); 339 340 return std::error_code(); 341} 342 343std::error_code create_hard_link(const Twine &to, const Twine &from) { 344 // Get arguments. 345 SmallString<128> from_storage; 346 SmallString<128> to_storage; 347 StringRef f = from.toNullTerminatedStringRef(from_storage); 348 StringRef t = to.toNullTerminatedStringRef(to_storage); 349 350 if (::link(t.begin(), f.begin()) == -1) 351 return std::error_code(errno, std::generic_category()); 352 353 return std::error_code(); 354} 355 356std::error_code remove(const Twine &path, bool IgnoreNonExisting) { 357 SmallString<128> path_storage; 358 StringRef p = path.toNullTerminatedStringRef(path_storage); 359 360 struct stat buf; 361 if (lstat(p.begin(), &buf) != 0) { 362 if (errno != ENOENT || !IgnoreNonExisting) 363 return std::error_code(errno, std::generic_category()); 364 return std::error_code(); 365 } 366 367 // Note: this check catches strange situations. In all cases, LLVM should 368 // only be involved in the creation and deletion of regular files. This 369 // check ensures that what we're trying to erase is a regular file. It 370 // effectively prevents LLVM from erasing things like /dev/null, any block 371 // special file, or other things that aren't "regular" files. 372 if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode)) 373 return make_error_code(errc::operation_not_permitted); 374 375 if (::remove(p.begin()) == -1) { 376 if (errno != ENOENT || !IgnoreNonExisting) 377 return std::error_code(errno, std::generic_category()); 378 } 379 380 return std::error_code(); 381} 382 383static bool is_local_impl(struct STATVFS &Vfs) { 384#if defined(__linux__) || defined(__GNU__) 385#ifndef NFS_SUPER_MAGIC 386#define NFS_SUPER_MAGIC 0x6969 387#endif 388#ifndef SMB_SUPER_MAGIC 389#define SMB_SUPER_MAGIC 0x517B 390#endif 391#ifndef CIFS_MAGIC_NUMBER 392#define CIFS_MAGIC_NUMBER 0xFF534D42 393#endif 394#ifdef __GNU__ 395 switch ((uint32_t)Vfs.__f_type) { 396#else 397 switch ((uint32_t)Vfs.f_type) { 398#endif 399 case NFS_SUPER_MAGIC: 400 case SMB_SUPER_MAGIC: 401 case CIFS_MAGIC_NUMBER: 402 return false; 403 default: 404 return true; 405 } 406#elif defined(__CYGWIN__) 407 // Cygwin doesn't expose this information; would need to use Win32 API. 408 return false; 409#elif defined(__Fuchsia__) 410 // Fuchsia doesn't yet support remote filesystem mounts. 411 return true; 412#elif defined(__HAIKU__) 413 // Haiku doesn't expose this information. 414 return false; 415#elif defined(__sun) 416 // statvfs::f_basetype contains a null-terminated FSType name of the mounted target 417 StringRef fstype(Vfs.f_basetype); 418 // NFS is the only non-local fstype?? 419 return !fstype.equals("nfs"); 420#elif defined(_AIX) 421 // Call mntctl; try more than twice in case of timing issues with a concurrent 422 // mount. 423 int Ret; 424 size_t BufSize = 2048u; 425 std::unique_ptr<char[]> Buf; 426 int Tries = 3; 427 while (Tries--) { 428 Buf = llvm::make_unique<char[]>(BufSize); 429 Ret = mntctl(MCTL_QUERY, BufSize, Buf.get()); 430 if (Ret != 0) 431 break; 432 BufSize = *reinterpret_cast<unsigned int *>(Buf.get()); 433 Buf.reset(); 434 } 435 436 if (Ret == -1) 437 // There was an error; "remote" is the conservative answer. 438 return false; 439 440 // Look for the correct vmount entry. 441 char *CurObjPtr = Buf.get(); 442 while (Ret--) { 443 struct vmount *Vp = reinterpret_cast<struct vmount *>(CurObjPtr); 444 static_assert(sizeof(Vfs.f_fsid) == sizeof(Vp->vmt_fsid), 445 "fsid length mismatch"); 446 if (memcmp(&Vfs.f_fsid, &Vp->vmt_fsid, sizeof Vfs.f_fsid) == 0) 447 return (Vp->vmt_flags & MNT_REMOTE) == 0; 448 449 CurObjPtr += Vp->vmt_length; 450 } 451 452 // vmount entry not found; "remote" is the conservative answer. 453 return false; 454#else 455 return !!(STATVFS_F_FLAG(Vfs) & MNT_LOCAL); 456#endif 457} 458 459std::error_code is_local(const Twine &Path, bool &Result) { 460 struct STATVFS Vfs; 461 if (::STATVFS(const_cast<char *>(Path.str().c_str()), &Vfs)) 462 return std::error_code(errno, std::generic_category()); 463 464 Result = is_local_impl(Vfs); 465 return std::error_code(); 466} 467 468std::error_code is_local(int FD, bool &Result) { 469 struct STATVFS Vfs; 470 if (::FSTATVFS(FD, &Vfs)) 471 return std::error_code(errno, std::generic_category()); 472 473 Result = is_local_impl(Vfs); 474 return std::error_code(); 475} 476 477std::error_code rename(const Twine &from, const Twine &to) { 478 // Get arguments. 479 SmallString<128> from_storage; 480 SmallString<128> to_storage; 481 StringRef f = from.toNullTerminatedStringRef(from_storage); 482 StringRef t = to.toNullTerminatedStringRef(to_storage); 483 484 if (::rename(f.begin(), t.begin()) == -1) 485 return std::error_code(errno, std::generic_category()); 486 487 return std::error_code(); 488} 489 490std::error_code resize_file(int FD, uint64_t Size) { 491#if defined(HAVE_POSIX_FALLOCATE) 492 // If we have posix_fallocate use it. Unlike ftruncate it always allocates 493 // space, so we get an error if the disk is full. 494 if (int Err = ::posix_fallocate(FD, 0, Size)) { 495 if (Err != EINVAL && Err != EOPNOTSUPP) 496 return std::error_code(Err, std::generic_category()); 497 } 498#endif 499 // Use ftruncate as a fallback. It may or may not allocate space. At least on 500 // OS X with HFS+ it does. 501 if (::ftruncate(FD, Size) == -1) 502 return std::error_code(errno, std::generic_category()); 503 504 return std::error_code(); 505} 506 507static int convertAccessMode(AccessMode Mode) { 508 switch (Mode) { 509 case AccessMode::Exist: 510 return F_OK; 511 case AccessMode::Write: 512 return W_OK; 513 case AccessMode::Execute: 514 return R_OK | X_OK; // scripts also need R_OK. 515 } 516 llvm_unreachable("invalid enum"); 517} 518 519std::error_code access(const Twine &Path, AccessMode Mode) { 520 SmallString<128> PathStorage; 521 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 522 523 if (::access(P.begin(), convertAccessMode(Mode)) == -1) 524 return std::error_code(errno, std::generic_category()); 525 526 if (Mode == AccessMode::Execute) { 527 // Don't say that directories are executable. 528 struct stat buf; 529 if (0 != stat(P.begin(), &buf)) 530 return errc::permission_denied; 531 if (!S_ISREG(buf.st_mode)) 532 return errc::permission_denied; 533 } 534 535 return std::error_code(); 536} 537 538bool can_execute(const Twine &Path) { 539 return !access(Path, AccessMode::Execute); 540} 541 542bool equivalent(file_status A, file_status B) { 543 assert(status_known(A) && status_known(B)); 544 return A.fs_st_dev == B.fs_st_dev && 545 A.fs_st_ino == B.fs_st_ino; 546} 547 548std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { 549 file_status fsA, fsB; 550 if (std::error_code ec = status(A, fsA)) 551 return ec; 552 if (std::error_code ec = status(B, fsB)) 553 return ec; 554 result = equivalent(fsA, fsB); 555 return std::error_code(); 556} 557 558static void expandTildeExpr(SmallVectorImpl<char> &Path) { 559 StringRef PathStr(Path.begin(), Path.size()); 560 if (PathStr.empty() || !PathStr.startswith("~")) 561 return; 562 563 PathStr = PathStr.drop_front(); 564 StringRef Expr = 565 PathStr.take_until([](char c) { return path::is_separator(c); }); 566 StringRef Remainder = PathStr.substr(Expr.size() + 1); 567 SmallString<128> Storage; 568 if (Expr.empty()) { 569 // This is just ~/..., resolve it to the current user's home dir. 570 if (!path::home_directory(Storage)) { 571 // For some reason we couldn't get the home directory. Just exit. 572 return; 573 } 574 575 // Overwrite the first character and insert the rest. 576 Path[0] = Storage[0]; 577 Path.insert(Path.begin() + 1, Storage.begin() + 1, Storage.end()); 578 return; 579 } 580 581 // This is a string of the form ~username/, look up this user's entry in the 582 // password database. 583 struct passwd *Entry = nullptr; 584 std::string User = Expr.str(); 585 Entry = ::getpwnam(User.c_str()); 586 587 if (!Entry) { 588 // Unable to look up the entry, just return back the original path. 589 return; 590 } 591 592 Storage = Remainder; 593 Path.clear(); 594 Path.append(Entry->pw_dir, Entry->pw_dir + strlen(Entry->pw_dir)); 595 llvm::sys::path::append(Path, Storage); 596} 597 598 599void expand_tilde(const Twine &path, SmallVectorImpl<char> &dest) { 600 dest.clear(); 601 if (path.isTriviallyEmpty()) 602 return; 603 604 path.toVector(dest); 605 expandTildeExpr(dest); 606 607 return; 608} 609 610static file_type typeForMode(mode_t Mode) { 611 if (S_ISDIR(Mode)) 612 return file_type::directory_file; 613 else if (S_ISREG(Mode)) 614 return file_type::regular_file; 615 else if (S_ISBLK(Mode)) 616 return file_type::block_file; 617 else if (S_ISCHR(Mode)) 618 return file_type::character_file; 619 else if (S_ISFIFO(Mode)) 620 return file_type::fifo_file; 621 else if (S_ISSOCK(Mode)) 622 return file_type::socket_file; 623 else if (S_ISLNK(Mode)) 624 return file_type::symlink_file; 625 return file_type::type_unknown; 626} 627 628static std::error_code fillStatus(int StatRet, const struct stat &Status, 629 file_status &Result) { 630 if (StatRet != 0) { 631 std::error_code EC(errno, std::generic_category()); 632 if (EC == errc::no_such_file_or_directory) 633 Result = file_status(file_type::file_not_found); 634 else 635 Result = file_status(file_type::status_error); 636 return EC; 637 } 638 639 uint32_t atime_nsec, mtime_nsec; 640#if defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) 641 atime_nsec = Status.st_atimespec.tv_nsec; 642 mtime_nsec = Status.st_mtimespec.tv_nsec; 643#elif defined(HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC) 644 atime_nsec = Status.st_atim.tv_nsec; 645 mtime_nsec = Status.st_mtim.tv_nsec; 646#else 647 atime_nsec = mtime_nsec = 0; 648#endif 649 650 perms Perms = static_cast<perms>(Status.st_mode) & all_perms; 651 Result = file_status(typeForMode(Status.st_mode), Perms, Status.st_dev, 652 Status.st_nlink, Status.st_ino, 653 Status.st_atime, atime_nsec, Status.st_mtime, mtime_nsec, 654 Status.st_uid, Status.st_gid, Status.st_size); 655 656 return std::error_code(); 657} 658 659std::error_code status(const Twine &Path, file_status &Result, bool Follow) { 660 SmallString<128> PathStorage; 661 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 662 663 struct stat Status; 664 int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status); 665 return fillStatus(StatRet, Status, Result); 666} 667 668std::error_code status(int FD, file_status &Result) { 669 struct stat Status; 670 int StatRet = ::fstat(FD, &Status); 671 return fillStatus(StatRet, Status, Result); 672} 673 674std::error_code setPermissions(const Twine &Path, perms Permissions) { 675 SmallString<128> PathStorage; 676 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 677 678 if (::chmod(P.begin(), Permissions)) 679 return std::error_code(errno, std::generic_category()); 680 return std::error_code(); 681} 682 683std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, 684 TimePoint<> ModificationTime) { 685#if defined(HAVE_FUTIMENS) 686 timespec Times[2]; 687 Times[0] = sys::toTimeSpec(AccessTime); 688 Times[1] = sys::toTimeSpec(ModificationTime); 689 if (::futimens(FD, Times)) 690 return std::error_code(errno, std::generic_category()); 691 return std::error_code(); 692#elif defined(HAVE_FUTIMES) 693 timeval Times[2]; 694 Times[0] = sys::toTimeVal( 695 std::chrono::time_point_cast<std::chrono::microseconds>(AccessTime)); 696 Times[1] = 697 sys::toTimeVal(std::chrono::time_point_cast<std::chrono::microseconds>( 698 ModificationTime)); 699 if (::futimes(FD, Times)) 700 return std::error_code(errno, std::generic_category()); 701 return std::error_code(); 702#else 703#warning Missing futimes() and futimens() 704 return make_error_code(errc::function_not_supported); 705#endif 706} 707 708std::error_code mapped_file_region::init(int FD, uint64_t Offset, 709 mapmode Mode) { 710 assert(Size != 0); 711 712 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; 713 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); 714#if defined(__APPLE__) 715 //---------------------------------------------------------------------- 716 // Newer versions of MacOSX have a flag that will allow us to read from 717 // binaries whose code signature is invalid without crashing by using 718 // the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media 719 // is mapped we can avoid crashing and return zeroes to any pages we try 720 // to read if the media becomes unavailable by using the 721 // MAP_RESILIENT_MEDIA flag. These flags are only usable when mapping 722 // with PROT_READ, so take care not to specify them otherwise. 723 //---------------------------------------------------------------------- 724 if (Mode == readonly) { 725#if defined(MAP_RESILIENT_CODESIGN) 726 flags |= MAP_RESILIENT_CODESIGN; 727#endif 728#if defined(MAP_RESILIENT_MEDIA) 729 flags |= MAP_RESILIENT_MEDIA; 730#endif 731 } 732#endif // #if defined (__APPLE__) 733 734 Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset); 735 if (Mapping == MAP_FAILED) 736 return std::error_code(errno, std::generic_category()); 737 return std::error_code(); 738} 739 740mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length, 741 uint64_t offset, std::error_code &ec) 742 : Size(length), Mapping(), Mode(mode) { 743 (void)Mode; 744 ec = init(fd, offset, mode); 745 if (ec) 746 Mapping = nullptr; 747} 748 749mapped_file_region::~mapped_file_region() { 750 if (Mapping) 751 ::munmap(Mapping, Size); 752} 753 754size_t mapped_file_region::size() const { 755 assert(Mapping && "Mapping failed but used anyway!"); 756 return Size; 757} 758 759char *mapped_file_region::data() const { 760 assert(Mapping && "Mapping failed but used anyway!"); 761 return reinterpret_cast<char*>(Mapping); 762} 763 764const char *mapped_file_region::const_data() const { 765 assert(Mapping && "Mapping failed but used anyway!"); 766 return reinterpret_cast<const char*>(Mapping); 767} 768 769int mapped_file_region::alignment() { 770 return Process::getPageSize(); 771} 772 773std::error_code detail::directory_iterator_construct(detail::DirIterState &it, 774 StringRef path, 775 bool follow_symlinks) { 776 SmallString<128> path_null(path); 777 DIR *directory = ::opendir(path_null.c_str()); 778 if (!directory) 779 return std::error_code(errno, std::generic_category()); 780 781 it.IterationHandle = reinterpret_cast<intptr_t>(directory); 782 // Add something for replace_filename to replace. 783 path::append(path_null, "."); 784 it.CurrentEntry = directory_entry(path_null.str(), follow_symlinks); 785 return directory_iterator_increment(it); 786} 787 788std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { 789 if (it.IterationHandle) 790 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle)); 791 it.IterationHandle = 0; 792 it.CurrentEntry = directory_entry(); 793 return std::error_code(); 794} 795 796static file_type direntType(dirent* Entry) { 797 // Most platforms provide the file type in the dirent: Linux/BSD/Mac. 798 // The DTTOIF macro lets us reuse our status -> type conversion. 799#if defined(_DIRENT_HAVE_D_TYPE) && defined(DTTOIF) 800 return typeForMode(DTTOIF(Entry->d_type)); 801#else 802 // Other platforms such as Solaris require a stat() to get the type. 803 return file_type::type_unknown; 804#endif 805} 806 807std::error_code detail::directory_iterator_increment(detail::DirIterState &It) { 808 errno = 0; 809 dirent *CurDir = ::readdir(reinterpret_cast<DIR *>(It.IterationHandle)); 810 if (CurDir == nullptr && errno != 0) { 811 return std::error_code(errno, std::generic_category()); 812 } else if (CurDir != nullptr) { 813 StringRef Name(CurDir->d_name); 814 if ((Name.size() == 1 && Name[0] == '.') || 815 (Name.size() == 2 && Name[0] == '.' && Name[1] == '.')) 816 return directory_iterator_increment(It); 817 It.CurrentEntry.replace_filename(Name, direntType(CurDir)); 818 } else 819 return directory_iterator_destruct(It); 820 821 return std::error_code(); 822} 823 824ErrorOr<basic_file_status> directory_entry::status() const { 825 file_status s; 826 if (auto EC = fs::status(Path, s, FollowSymlinks)) 827 return EC; 828 return s; 829} 830 831#if !defined(F_GETPATH) 832static bool hasProcSelfFD() { 833 // If we have a /proc filesystem mounted, we can quickly establish the 834 // real name of the file with readlink 835 static const bool Result = (::access("/proc/self/fd", R_OK) == 0); 836 return Result; 837} 838#endif 839 840static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags, 841 FileAccess Access) { 842 int Result = 0; 843 if (Access == FA_Read) 844 Result |= O_RDONLY; 845 else if (Access == FA_Write) 846 Result |= O_WRONLY; 847 else if (Access == (FA_Read | FA_Write)) 848 Result |= O_RDWR; 849 850 // This is for compatibility with old code that assumed F_Append implied 851 // would open an existing file. See Windows/Path.inc for a longer comment. 852 if (Flags & F_Append) 853 Disp = CD_OpenAlways; 854 855 if (Disp == CD_CreateNew) { 856 Result |= O_CREAT; // Create if it doesn't exist. 857 Result |= O_EXCL; // Fail if it does. 858 } else if (Disp == CD_CreateAlways) { 859 Result |= O_CREAT; // Create if it doesn't exist. 860 Result |= O_TRUNC; // Truncate if it does. 861 } else if (Disp == CD_OpenAlways) { 862 Result |= O_CREAT; // Create if it doesn't exist. 863 } else if (Disp == CD_OpenExisting) { 864 // Nothing special, just don't add O_CREAT and we get these semantics. 865 } 866 867 if (Flags & F_Append) 868 Result |= O_APPEND; 869 870#ifdef O_CLOEXEC 871 if (!(Flags & OF_ChildInherit)) 872 Result |= O_CLOEXEC; 873#endif 874 875 return Result; 876} 877 878std::error_code openFile(const Twine &Name, int &ResultFD, 879 CreationDisposition Disp, FileAccess Access, 880 OpenFlags Flags, unsigned Mode) { 881 int OpenFlags = nativeOpenFlags(Disp, Flags, Access); 882 883 SmallString<128> Storage; 884 StringRef P = Name.toNullTerminatedStringRef(Storage); 885 // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal 886 // when open is overloaded, such as in Bionic. 887 auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); }; 888 if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0) 889 return std::error_code(errno, std::generic_category()); 890#ifndef O_CLOEXEC 891 if (!(Flags & OF_ChildInherit)) { 892 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC); 893 (void)r; 894 assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed"); 895 } 896#endif 897 return std::error_code(); 898} 899 900Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp, 901 FileAccess Access, OpenFlags Flags, 902 unsigned Mode) { 903 904 int FD; 905 std::error_code EC = openFile(Name, FD, Disp, Access, Flags, Mode); 906 if (EC) 907 return errorCodeToError(EC); 908 return FD; 909} 910 911std::error_code openFileForRead(const Twine &Name, int &ResultFD, 912 OpenFlags Flags, 913 SmallVectorImpl<char> *RealPath) { 914 std::error_code EC = 915 openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666); 916 if (EC) 917 return EC; 918 919 // Attempt to get the real name of the file, if the user asked 920 if(!RealPath) 921 return std::error_code(); 922 RealPath->clear(); 923#if defined(F_GETPATH) 924 // When F_GETPATH is availble, it is the quickest way to get 925 // the real path name. 926 char Buffer[MAXPATHLEN]; 927 if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1) 928 RealPath->append(Buffer, Buffer + strlen(Buffer)); 929#else 930 char Buffer[PATH_MAX]; 931 if (hasProcSelfFD()) { 932 char ProcPath[64]; 933 snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD); 934 ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer)); 935 if (CharCount > 0) 936 RealPath->append(Buffer, Buffer + CharCount); 937 } else { 938 SmallString<128> Storage; 939 StringRef P = Name.toNullTerminatedStringRef(Storage); 940 941 // Use ::realpath to get the real path name 942 if (::realpath(P.begin(), Buffer) != nullptr) 943 RealPath->append(Buffer, Buffer + strlen(Buffer)); 944 } 945#endif 946 return std::error_code(); 947} 948 949Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags, 950 SmallVectorImpl<char> *RealPath) { 951 file_t ResultFD; 952 std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath); 953 if (EC) 954 return errorCodeToError(EC); 955 return ResultFD; 956} 957 958void closeFile(file_t &F) { 959 ::close(F); 960 F = kInvalidFile; 961} 962 963template <typename T> 964static std::error_code remove_directories_impl(const T &Entry, 965 bool IgnoreErrors) { 966 std::error_code EC; 967 directory_iterator Begin(Entry, EC, false); 968 directory_iterator End; 969 while (Begin != End) { 970 auto &Item = *Begin; 971 ErrorOr<basic_file_status> st = Item.status(); 972 if (!st && !IgnoreErrors) 973 return st.getError(); 974 975 if (is_directory(*st)) { 976 EC = remove_directories_impl(Item, IgnoreErrors); 977 if (EC && !IgnoreErrors) 978 return EC; 979 } 980 981 EC = fs::remove(Item.path(), true); 982 if (EC && !IgnoreErrors) 983 return EC; 984 985 Begin.increment(EC); 986 if (EC && !IgnoreErrors) 987 return EC; 988 } 989 return std::error_code(); 990} 991 992std::error_code remove_directories(const Twine &path, bool IgnoreErrors) { 993 auto EC = remove_directories_impl(path, IgnoreErrors); 994 if (EC && !IgnoreErrors) 995 return EC; 996 EC = fs::remove(path, true); 997 if (EC && !IgnoreErrors) 998 return EC; 999 return std::error_code(); 1000} 1001 1002std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest, 1003 bool expand_tilde) { 1004 dest.clear(); 1005 if (path.isTriviallyEmpty()) 1006 return std::error_code(); 1007 1008 if (expand_tilde) { 1009 SmallString<128> Storage; 1010 path.toVector(Storage); 1011 expandTildeExpr(Storage); 1012 return real_path(Storage, dest, false); 1013 } 1014 1015 SmallString<128> Storage; 1016 StringRef P = path.toNullTerminatedStringRef(Storage); 1017 char Buffer[PATH_MAX]; 1018 if (::realpath(P.begin(), Buffer) == nullptr) 1019 return std::error_code(errno, std::generic_category()); 1020 dest.append(Buffer, Buffer + strlen(Buffer)); 1021 return std::error_code(); 1022} 1023 1024} // end namespace fs 1025 1026namespace path { 1027 1028bool home_directory(SmallVectorImpl<char> &result) { 1029 char *RequestedDir = getenv("HOME"); 1030 if (!RequestedDir) { 1031 struct passwd *pw = getpwuid(getuid()); 1032 if (pw && pw->pw_dir) 1033 RequestedDir = pw->pw_dir; 1034 } 1035 if (!RequestedDir) 1036 return false; 1037 1038 result.clear(); 1039 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1040 return true; 1041} 1042 1043static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) { 1044 #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) 1045 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. 1046 // macros defined in <unistd.h> on darwin >= 9 1047 int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR 1048 : _CS_DARWIN_USER_CACHE_DIR; 1049 size_t ConfLen = confstr(ConfName, nullptr, 0); 1050 if (ConfLen > 0) { 1051 do { 1052 Result.resize(ConfLen); 1053 ConfLen = confstr(ConfName, Result.data(), Result.size()); 1054 } while (ConfLen > 0 && ConfLen != Result.size()); 1055 1056 if (ConfLen > 0) { 1057 assert(Result.back() == 0); 1058 Result.pop_back(); 1059 return true; 1060 } 1061 1062 Result.clear(); 1063 } 1064 #endif 1065 return false; 1066} 1067 1068static const char *getEnvTempDir() { 1069 // Check whether the temporary directory is specified by an environment 1070 // variable. 1071 const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; 1072 for (const char *Env : EnvironmentVariables) { 1073 if (const char *Dir = std::getenv(Env)) 1074 return Dir; 1075 } 1076 1077 return nullptr; 1078} 1079 1080static const char *getDefaultTempDir(bool ErasedOnReboot) { 1081#ifdef P_tmpdir 1082 if ((bool)P_tmpdir) 1083 return P_tmpdir; 1084#endif 1085 1086 if (ErasedOnReboot) 1087 return "/tmp"; 1088 return "/var/tmp"; 1089} 1090 1091void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { 1092 Result.clear(); 1093 1094 if (ErasedOnReboot) { 1095 // There is no env variable for the cache directory. 1096 if (const char *RequestedDir = getEnvTempDir()) { 1097 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1098 return; 1099 } 1100 } 1101 1102 if (getDarwinConfDir(ErasedOnReboot, Result)) 1103 return; 1104 1105 const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); 1106 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1107} 1108 1109} // end namespace path 1110 1111} // end namespace sys 1112} // end namespace llvm 1113