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