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__) 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); 233} 234 235TimePoint<> basic_file_status::getLastModificationTime() const { 236 return toTimePoint(fs_st_mtime); 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 perms Perms = static_cast<perms>(Status.st_mode) & all_perms; 595 Result = file_status(typeForMode(Status.st_mode), Perms, Status.st_dev, 596 Status.st_nlink, Status.st_ino, Status.st_atime, 597 Status.st_mtime, Status.st_uid, Status.st_gid, 598 Status.st_size); 599 600 return std::error_code(); 601} 602 603std::error_code status(const Twine &Path, file_status &Result, bool Follow) { 604 SmallString<128> PathStorage; 605 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 606 607 struct stat Status; 608 int StatRet = (Follow ? ::stat : ::lstat)(P.begin(), &Status); 609 return fillStatus(StatRet, Status, Result); 610} 611 612std::error_code status(int FD, file_status &Result) { 613 struct stat Status; 614 int StatRet = ::fstat(FD, &Status); 615 return fillStatus(StatRet, Status, Result); 616} 617 618std::error_code setPermissions(const Twine &Path, perms Permissions) { 619 SmallString<128> PathStorage; 620 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 621 622 if (::chmod(P.begin(), Permissions)) 623 return std::error_code(errno, std::generic_category()); 624 return std::error_code(); 625} 626 627std::error_code setLastAccessAndModificationTime(int FD, TimePoint<> AccessTime, 628 TimePoint<> ModificationTime) { 629#if defined(HAVE_FUTIMENS) 630 timespec Times[2]; 631 Times[0] = sys::toTimeSpec(AccessTime); 632 Times[1] = sys::toTimeSpec(ModificationTime); 633 if (::futimens(FD, Times)) 634 return std::error_code(errno, std::generic_category()); 635 return std::error_code(); 636#elif defined(HAVE_FUTIMES) 637 timeval Times[2]; 638 Times[0] = sys::toTimeVal( 639 std::chrono::time_point_cast<std::chrono::microseconds>(AccessTime)); 640 Times[1] = 641 sys::toTimeVal(std::chrono::time_point_cast<std::chrono::microseconds>( 642 ModificationTime)); 643 if (::futimes(FD, Times)) 644 return std::error_code(errno, std::generic_category()); 645 return std::error_code(); 646#else 647#warning Missing futimes() and futimens() 648 return make_error_code(errc::function_not_supported); 649#endif 650} 651 652std::error_code mapped_file_region::init(int FD, uint64_t Offset, 653 mapmode Mode) { 654 assert(Size != 0); 655 656 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; 657 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); 658#if defined(__APPLE__) 659 //---------------------------------------------------------------------- 660 // Newer versions of MacOSX have a flag that will allow us to read from 661 // binaries whose code signature is invalid without crashing by using 662 // the MAP_RESILIENT_CODESIGN flag. Also if a file from removable media 663 // is mapped we can avoid crashing and return zeroes to any pages we try 664 // to read if the media becomes unavailable by using the 665 // MAP_RESILIENT_MEDIA flag. These flags are only usable when mapping 666 // with PROT_READ, so take care not to specify them otherwise. 667 //---------------------------------------------------------------------- 668 if (Mode == readonly) { 669#if defined(MAP_RESILIENT_CODESIGN) 670 flags |= MAP_RESILIENT_CODESIGN; 671#endif 672#if defined(MAP_RESILIENT_MEDIA) 673 flags |= MAP_RESILIENT_MEDIA; 674#endif 675 } 676#endif // #if defined (__APPLE__) 677 678 Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset); 679 if (Mapping == MAP_FAILED) 680 return std::error_code(errno, std::generic_category()); 681 return std::error_code(); 682} 683 684mapped_file_region::mapped_file_region(int fd, mapmode mode, size_t length, 685 uint64_t offset, std::error_code &ec) 686 : Size(length), Mapping(), Mode(mode) { 687 (void)Mode; 688 ec = init(fd, offset, mode); 689 if (ec) 690 Mapping = nullptr; 691} 692 693mapped_file_region::~mapped_file_region() { 694 if (Mapping) 695 ::munmap(Mapping, Size); 696} 697 698size_t mapped_file_region::size() const { 699 assert(Mapping && "Mapping failed but used anyway!"); 700 return Size; 701} 702 703char *mapped_file_region::data() const { 704 assert(Mapping && "Mapping failed but used anyway!"); 705 return reinterpret_cast<char*>(Mapping); 706} 707 708const char *mapped_file_region::const_data() const { 709 assert(Mapping && "Mapping failed but used anyway!"); 710 return reinterpret_cast<const char*>(Mapping); 711} 712 713int mapped_file_region::alignment() { 714 return Process::getPageSize(); 715} 716 717std::error_code detail::directory_iterator_construct(detail::DirIterState &it, 718 StringRef path, 719 bool follow_symlinks) { 720 SmallString<128> path_null(path); 721 DIR *directory = ::opendir(path_null.c_str()); 722 if (!directory) 723 return std::error_code(errno, std::generic_category()); 724 725 it.IterationHandle = reinterpret_cast<intptr_t>(directory); 726 // Add something for replace_filename to replace. 727 path::append(path_null, "."); 728 it.CurrentEntry = directory_entry(path_null.str(), follow_symlinks); 729 return directory_iterator_increment(it); 730} 731 732std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { 733 if (it.IterationHandle) 734 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle)); 735 it.IterationHandle = 0; 736 it.CurrentEntry = directory_entry(); 737 return std::error_code(); 738} 739 740static file_type direntType(dirent* Entry) { 741 // Most platforms provide the file type in the dirent: Linux/BSD/Mac. 742 // The DTTOIF macro lets us reuse our status -> type conversion. 743#if defined(_DIRENT_HAVE_D_TYPE) && defined(DTTOIF) 744 return typeForMode(DTTOIF(Entry->d_type)); 745#else 746 // Other platforms such as Solaris require a stat() to get the type. 747 return file_type::type_unknown; 748#endif 749} 750 751std::error_code detail::directory_iterator_increment(detail::DirIterState &It) { 752 errno = 0; 753 dirent *CurDir = ::readdir(reinterpret_cast<DIR *>(It.IterationHandle)); 754 if (CurDir == nullptr && errno != 0) { 755 return std::error_code(errno, std::generic_category()); 756 } else if (CurDir != nullptr) { 757 StringRef Name(CurDir->d_name); 758 if ((Name.size() == 1 && Name[0] == '.') || 759 (Name.size() == 2 && Name[0] == '.' && Name[1] == '.')) 760 return directory_iterator_increment(It); 761 It.CurrentEntry.replace_filename(Name, direntType(CurDir)); 762 } else 763 return directory_iterator_destruct(It); 764 765 return std::error_code(); 766} 767 768ErrorOr<basic_file_status> directory_entry::status() const { 769 file_status s; 770 if (auto EC = fs::status(Path, s, FollowSymlinks)) 771 return EC; 772 return s; 773} 774 775#if !defined(F_GETPATH) 776static bool hasProcSelfFD() { 777 // If we have a /proc filesystem mounted, we can quickly establish the 778 // real name of the file with readlink 779 static const bool Result = (::access("/proc/self/fd", R_OK) == 0); 780 return Result; 781} 782#endif 783 784static int nativeOpenFlags(CreationDisposition Disp, OpenFlags Flags, 785 FileAccess Access) { 786 int Result = 0; 787 if (Access == FA_Read) 788 Result |= O_RDONLY; 789 else if (Access == FA_Write) 790 Result |= O_WRONLY; 791 else if (Access == (FA_Read | FA_Write)) 792 Result |= O_RDWR; 793 794 // This is for compatibility with old code that assumed F_Append implied 795 // would open an existing file. See Windows/Path.inc for a longer comment. 796 if (Flags & F_Append) 797 Disp = CD_OpenAlways; 798 799 if (Disp == CD_CreateNew) { 800 Result |= O_CREAT; // Create if it doesn't exist. 801 Result |= O_EXCL; // Fail if it does. 802 } else if (Disp == CD_CreateAlways) { 803 Result |= O_CREAT; // Create if it doesn't exist. 804 Result |= O_TRUNC; // Truncate if it does. 805 } else if (Disp == CD_OpenAlways) { 806 Result |= O_CREAT; // Create if it doesn't exist. 807 } else if (Disp == CD_OpenExisting) { 808 // Nothing special, just don't add O_CREAT and we get these semantics. 809 } 810 811 if (Flags & F_Append) 812 Result |= O_APPEND; 813 814#ifdef O_CLOEXEC 815 if (!(Flags & OF_ChildInherit)) 816 Result |= O_CLOEXEC; 817#endif 818 819 return Result; 820} 821 822std::error_code openFile(const Twine &Name, int &ResultFD, 823 CreationDisposition Disp, FileAccess Access, 824 OpenFlags Flags, unsigned Mode) { 825 int OpenFlags = nativeOpenFlags(Disp, Flags, Access); 826 827 SmallString<128> Storage; 828 StringRef P = Name.toNullTerminatedStringRef(Storage); 829 // Call ::open in a lambda to avoid overload resolution in RetryAfterSignal 830 // when open is overloaded, such as in Bionic. 831 auto Open = [&]() { return ::open(P.begin(), OpenFlags, Mode); }; 832 if ((ResultFD = sys::RetryAfterSignal(-1, Open)) < 0) 833 return std::error_code(errno, std::generic_category()); 834#ifndef O_CLOEXEC 835 if (!(Flags & OF_ChildInherit)) { 836 int r = fcntl(ResultFD, F_SETFD, FD_CLOEXEC); 837 (void)r; 838 assert(r == 0 && "fcntl(F_SETFD, FD_CLOEXEC) failed"); 839 } 840#endif 841 return std::error_code(); 842} 843 844Expected<int> openNativeFile(const Twine &Name, CreationDisposition Disp, 845 FileAccess Access, OpenFlags Flags, 846 unsigned Mode) { 847 848 int FD; 849 std::error_code EC = openFile(Name, FD, Disp, Access, Flags, Mode); 850 if (EC) 851 return errorCodeToError(EC); 852 return FD; 853} 854 855std::error_code openFileForRead(const Twine &Name, int &ResultFD, 856 OpenFlags Flags, 857 SmallVectorImpl<char> *RealPath) { 858 std::error_code EC = 859 openFile(Name, ResultFD, CD_OpenExisting, FA_Read, Flags, 0666); 860 if (EC) 861 return EC; 862 863 // Attempt to get the real name of the file, if the user asked 864 if(!RealPath) 865 return std::error_code(); 866 RealPath->clear(); 867#if defined(F_GETPATH) 868 // When F_GETPATH is availble, it is the quickest way to get 869 // the real path name. 870 char Buffer[MAXPATHLEN]; 871 if (::fcntl(ResultFD, F_GETPATH, Buffer) != -1) 872 RealPath->append(Buffer, Buffer + strlen(Buffer)); 873#else 874 char Buffer[PATH_MAX]; 875 if (hasProcSelfFD()) { 876 char ProcPath[64]; 877 snprintf(ProcPath, sizeof(ProcPath), "/proc/self/fd/%d", ResultFD); 878 ssize_t CharCount = ::readlink(ProcPath, Buffer, sizeof(Buffer)); 879 if (CharCount > 0) 880 RealPath->append(Buffer, Buffer + CharCount); 881 } else { 882 SmallString<128> Storage; 883 StringRef P = Name.toNullTerminatedStringRef(Storage); 884 885 // Use ::realpath to get the real path name 886 if (::realpath(P.begin(), Buffer) != nullptr) 887 RealPath->append(Buffer, Buffer + strlen(Buffer)); 888 } 889#endif 890 return std::error_code(); 891} 892 893Expected<file_t> openNativeFileForRead(const Twine &Name, OpenFlags Flags, 894 SmallVectorImpl<char> *RealPath) { 895 file_t ResultFD; 896 std::error_code EC = openFileForRead(Name, ResultFD, Flags, RealPath); 897 if (EC) 898 return errorCodeToError(EC); 899 return ResultFD; 900} 901 902void closeFile(file_t &F) { 903 ::close(F); 904 F = kInvalidFile; 905} 906 907template <typename T> 908static std::error_code remove_directories_impl(const T &Entry, 909 bool IgnoreErrors) { 910 std::error_code EC; 911 directory_iterator Begin(Entry, EC, false); 912 directory_iterator End; 913 while (Begin != End) { 914 auto &Item = *Begin; 915 ErrorOr<basic_file_status> st = Item.status(); 916 if (!st && !IgnoreErrors) 917 return st.getError(); 918 919 if (is_directory(*st)) { 920 EC = remove_directories_impl(Item, IgnoreErrors); 921 if (EC && !IgnoreErrors) 922 return EC; 923 } 924 925 EC = fs::remove(Item.path(), true); 926 if (EC && !IgnoreErrors) 927 return EC; 928 929 Begin.increment(EC); 930 if (EC && !IgnoreErrors) 931 return EC; 932 } 933 return std::error_code(); 934} 935 936std::error_code remove_directories(const Twine &path, bool IgnoreErrors) { 937 auto EC = remove_directories_impl(path, IgnoreErrors); 938 if (EC && !IgnoreErrors) 939 return EC; 940 EC = fs::remove(path, true); 941 if (EC && !IgnoreErrors) 942 return EC; 943 return std::error_code(); 944} 945 946std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest, 947 bool expand_tilde) { 948 dest.clear(); 949 if (path.isTriviallyEmpty()) 950 return std::error_code(); 951 952 if (expand_tilde) { 953 SmallString<128> Storage; 954 path.toVector(Storage); 955 expandTildeExpr(Storage); 956 return real_path(Storage, dest, false); 957 } 958 959 SmallString<128> Storage; 960 StringRef P = path.toNullTerminatedStringRef(Storage); 961 char Buffer[PATH_MAX]; 962 if (::realpath(P.begin(), Buffer) == nullptr) 963 return std::error_code(errno, std::generic_category()); 964 dest.append(Buffer, Buffer + strlen(Buffer)); 965 return std::error_code(); 966} 967 968} // end namespace fs 969 970namespace path { 971 972bool home_directory(SmallVectorImpl<char> &result) { 973 char *RequestedDir = getenv("HOME"); 974 if (!RequestedDir) { 975 struct passwd *pw = getpwuid(getuid()); 976 if (pw && pw->pw_dir) 977 RequestedDir = pw->pw_dir; 978 } 979 if (!RequestedDir) 980 return false; 981 982 result.clear(); 983 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 984 return true; 985} 986 987static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) { 988 #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) 989 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. 990 // macros defined in <unistd.h> on darwin >= 9 991 int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR 992 : _CS_DARWIN_USER_CACHE_DIR; 993 size_t ConfLen = confstr(ConfName, nullptr, 0); 994 if (ConfLen > 0) { 995 do { 996 Result.resize(ConfLen); 997 ConfLen = confstr(ConfName, Result.data(), Result.size()); 998 } while (ConfLen > 0 && ConfLen != Result.size()); 999 1000 if (ConfLen > 0) { 1001 assert(Result.back() == 0); 1002 Result.pop_back(); 1003 return true; 1004 } 1005 1006 Result.clear(); 1007 } 1008 #endif 1009 return false; 1010} 1011 1012static const char *getEnvTempDir() { 1013 // Check whether the temporary directory is specified by an environment 1014 // variable. 1015 const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; 1016 for (const char *Env : EnvironmentVariables) { 1017 if (const char *Dir = std::getenv(Env)) 1018 return Dir; 1019 } 1020 1021 return nullptr; 1022} 1023 1024static const char *getDefaultTempDir(bool ErasedOnReboot) { 1025#ifdef P_tmpdir 1026 if ((bool)P_tmpdir) 1027 return P_tmpdir; 1028#endif 1029 1030 if (ErasedOnReboot) 1031 return "/tmp"; 1032 return "/var/tmp"; 1033} 1034 1035void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { 1036 Result.clear(); 1037 1038 if (ErasedOnReboot) { 1039 // There is no env variable for the cache directory. 1040 if (const char *RequestedDir = getEnvTempDir()) { 1041 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1042 return; 1043 } 1044 } 1045 1046 if (getDarwinConfDir(ErasedOnReboot, Result)) 1047 return; 1048 1049 const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); 1050 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 1051} 1052 1053} // end namespace path 1054 1055} // end namespace sys 1056} // end namespace llvm 1057