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_SYS_MMAN_H 29#include <sys/mman.h> 30#endif 31#if HAVE_DIRENT_H 32# include <dirent.h> 33# define NAMLEN(dirent) strlen((dirent)->d_name) 34#else 35# define dirent direct 36# define NAMLEN(dirent) (dirent)->d_namlen 37# if HAVE_SYS_NDIR_H 38# include <sys/ndir.h> 39# endif 40# if HAVE_SYS_DIR_H 41# include <sys/dir.h> 42# endif 43# if HAVE_NDIR_H 44# include <ndir.h> 45# endif 46#endif 47 48#ifdef __APPLE__ 49#include <mach-o/dyld.h> 50#endif 51 52// Both stdio.h and cstdio are included via different pathes and 53// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros 54// either. 55#undef ferror 56#undef feof 57 58// For GNU Hurd 59#if defined(__GNU__) && !defined(PATH_MAX) 60# define PATH_MAX 4096 61#endif 62 63#include <sys/types.h> 64#if !defined(__APPLE__) && !defined(__OpenBSD__) && !defined(__ANDROID__) 65#include <sys/statvfs.h> 66#define STATVFS statvfs 67#define STATVFS_F_FRSIZE(vfs) vfs.f_frsize 68#else 69#ifdef __OpenBSD__ 70#include <sys/param.h> 71#include <sys/mount.h> 72#elif defined(__ANDROID__) 73#include <sys/vfs.h> 74#else 75#include <sys/mount.h> 76#endif 77#define STATVFS statfs 78#define STATVFS_F_FRSIZE(vfs) static_cast<uint64_t>(vfs.f_bsize) 79#endif 80 81 82using namespace llvm; 83 84namespace llvm { 85namespace sys { 86namespace fs { 87#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 88 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \ 89 defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__) 90static int 91test_dir(char ret[PATH_MAX], const char *dir, const char *bin) 92{ 93 struct stat sb; 94 char fullpath[PATH_MAX]; 95 96 snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); 97 if (!realpath(fullpath, ret)) 98 return 1; 99 if (stat(fullpath, &sb) != 0) 100 return 1; 101 102 return 0; 103} 104 105static char * 106getprogpath(char ret[PATH_MAX], const char *bin) 107{ 108 char *pv, *s, *t; 109 110 /* First approach: absolute path. */ 111 if (bin[0] == '/') { 112 if (test_dir(ret, "/", bin) == 0) 113 return ret; 114 return nullptr; 115 } 116 117 /* Second approach: relative path. */ 118 if (strchr(bin, '/')) { 119 char cwd[PATH_MAX]; 120 if (!getcwd(cwd, PATH_MAX)) 121 return nullptr; 122 if (test_dir(ret, cwd, bin) == 0) 123 return ret; 124 return nullptr; 125 } 126 127 /* Third approach: $PATH */ 128 if ((pv = getenv("PATH")) == nullptr) 129 return nullptr; 130 s = pv = strdup(pv); 131 if (!pv) 132 return nullptr; 133 while ((t = strsep(&s, ":")) != nullptr) { 134 if (test_dir(ret, t, bin) == 0) { 135 free(pv); 136 return ret; 137 } 138 } 139 free(pv); 140 return nullptr; 141} 142#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ 143 144/// GetMainExecutable - Return the path to the main executable, given the 145/// value of argv[0] from program startup. 146std::string getMainExecutable(const char *argv0, void *MainAddr) { 147#if defined(__APPLE__) 148 // On OS X the executable path is saved to the stack by dyld. Reading it 149 // from there is much faster than calling dladdr, especially for large 150 // binaries with symbols. 151 char exe_path[MAXPATHLEN]; 152 uint32_t size = sizeof(exe_path); 153 if (_NSGetExecutablePath(exe_path, &size) == 0) { 154 char link_path[MAXPATHLEN]; 155 if (realpath(exe_path, link_path)) 156 return link_path; 157 } 158#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 159 defined(__OpenBSD__) || defined(__minix) || defined(__DragonFly__) || \ 160 defined(__FreeBSD_kernel__) 161 char exe_path[PATH_MAX]; 162 163 if (getprogpath(exe_path, argv0) != NULL) 164 return exe_path; 165#elif defined(__linux__) || defined(__CYGWIN__) 166 char exe_path[MAXPATHLEN]; 167 StringRef aPath("/proc/self/exe"); 168 if (sys::fs::exists(aPath)) { 169 // /proc is not always mounted under Linux (chroot for example). 170 ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); 171 if (len >= 0) 172 return std::string(exe_path, len); 173 } else { 174 // Fall back to the classical detection. 175 if (getprogpath(exe_path, argv0)) 176 return exe_path; 177 } 178#elif defined(HAVE_DLFCN_H) 179 // Use dladdr to get executable path if available. 180 Dl_info DLInfo; 181 int err = dladdr(MainAddr, &DLInfo); 182 if (err == 0) 183 return ""; 184 185 // If the filename is a symlink, we need to resolve and return the location of 186 // the actual executable. 187 char link_path[MAXPATHLEN]; 188 if (realpath(DLInfo.dli_fname, link_path)) 189 return link_path; 190#else 191#error GetMainExecutable is not implemented on this host yet. 192#endif 193 return ""; 194} 195 196TimeValue file_status::getLastAccessedTime() const { 197 TimeValue Ret; 198 Ret.fromEpochTime(fs_st_atime); 199 return Ret; 200} 201 202TimeValue file_status::getLastModificationTime() const { 203 TimeValue Ret; 204 Ret.fromEpochTime(fs_st_mtime); 205 return Ret; 206} 207 208UniqueID file_status::getUniqueID() const { 209 return UniqueID(fs_st_dev, fs_st_ino); 210} 211 212ErrorOr<space_info> disk_space(const Twine &Path) { 213 struct STATVFS Vfs; 214 if (::STATVFS(Path.str().c_str(), &Vfs)) 215 return std::error_code(errno, std::generic_category()); 216 auto FrSize = STATVFS_F_FRSIZE(Vfs); 217 space_info SpaceInfo; 218 SpaceInfo.capacity = static_cast<uint64_t>(Vfs.f_blocks) * FrSize; 219 SpaceInfo.free = static_cast<uint64_t>(Vfs.f_bfree) * FrSize; 220 SpaceInfo.available = static_cast<uint64_t>(Vfs.f_bavail) * FrSize; 221 return SpaceInfo; 222} 223 224std::error_code current_path(SmallVectorImpl<char> &result) { 225 result.clear(); 226 227 const char *pwd = ::getenv("PWD"); 228 llvm::sys::fs::file_status PWDStatus, DotStatus; 229 if (pwd && llvm::sys::path::is_absolute(pwd) && 230 !llvm::sys::fs::status(pwd, PWDStatus) && 231 !llvm::sys::fs::status(".", DotStatus) && 232 PWDStatus.getUniqueID() == DotStatus.getUniqueID()) { 233 result.append(pwd, pwd + strlen(pwd)); 234 return std::error_code(); 235 } 236 237#ifdef MAXPATHLEN 238 result.reserve(MAXPATHLEN); 239#else 240// For GNU Hurd 241 result.reserve(1024); 242#endif 243 244 while (true) { 245 if (::getcwd(result.data(), result.capacity()) == nullptr) { 246 // See if there was a real error. 247 if (errno != ENOMEM) 248 return std::error_code(errno, std::generic_category()); 249 // Otherwise there just wasn't enough space. 250 result.reserve(result.capacity() * 2); 251 } else 252 break; 253 } 254 255 result.set_size(strlen(result.data())); 256 return std::error_code(); 257} 258 259std::error_code create_directory(const Twine &path, bool IgnoreExisting, 260 perms Perms) { 261 SmallString<128> path_storage; 262 StringRef p = path.toNullTerminatedStringRef(path_storage); 263 264 if (::mkdir(p.begin(), Perms) == -1) { 265 if (errno != EEXIST || !IgnoreExisting) 266 return std::error_code(errno, std::generic_category()); 267 } 268 269 return std::error_code(); 270} 271 272// Note that we are using symbolic link because hard links are not supported by 273// all filesystems (SMB doesn't). 274std::error_code create_link(const Twine &to, const Twine &from) { 275 // Get arguments. 276 SmallString<128> from_storage; 277 SmallString<128> to_storage; 278 StringRef f = from.toNullTerminatedStringRef(from_storage); 279 StringRef t = to.toNullTerminatedStringRef(to_storage); 280 281 if (::symlink(t.begin(), f.begin()) == -1) 282 return std::error_code(errno, std::generic_category()); 283 284 return std::error_code(); 285} 286 287std::error_code remove(const Twine &path, bool IgnoreNonExisting) { 288 SmallString<128> path_storage; 289 StringRef p = path.toNullTerminatedStringRef(path_storage); 290 291 struct stat buf; 292 if (lstat(p.begin(), &buf) != 0) { 293 if (errno != ENOENT || !IgnoreNonExisting) 294 return std::error_code(errno, std::generic_category()); 295 return std::error_code(); 296 } 297 298 // Note: this check catches strange situations. In all cases, LLVM should 299 // only be involved in the creation and deletion of regular files. This 300 // check ensures that what we're trying to erase is a regular file. It 301 // effectively prevents LLVM from erasing things like /dev/null, any block 302 // special file, or other things that aren't "regular" files. 303 if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode)) 304 return make_error_code(errc::operation_not_permitted); 305 306 if (::remove(p.begin()) == -1) { 307 if (errno != ENOENT || !IgnoreNonExisting) 308 return std::error_code(errno, std::generic_category()); 309 } 310 311 return std::error_code(); 312} 313 314std::error_code rename(const Twine &from, const Twine &to) { 315 // Get arguments. 316 SmallString<128> from_storage; 317 SmallString<128> to_storage; 318 StringRef f = from.toNullTerminatedStringRef(from_storage); 319 StringRef t = to.toNullTerminatedStringRef(to_storage); 320 321 if (::rename(f.begin(), t.begin()) == -1) 322 return std::error_code(errno, std::generic_category()); 323 324 return std::error_code(); 325} 326 327std::error_code resize_file(int FD, uint64_t Size) { 328 if (::ftruncate(FD, Size) == -1) 329 return std::error_code(errno, std::generic_category()); 330 331 return std::error_code(); 332} 333 334static int convertAccessMode(AccessMode Mode) { 335 switch (Mode) { 336 case AccessMode::Exist: 337 return F_OK; 338 case AccessMode::Write: 339 return W_OK; 340 case AccessMode::Execute: 341 return R_OK | X_OK; // scripts also need R_OK. 342 } 343 llvm_unreachable("invalid enum"); 344} 345 346std::error_code access(const Twine &Path, AccessMode Mode) { 347 SmallString<128> PathStorage; 348 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 349 350 if (::access(P.begin(), convertAccessMode(Mode)) == -1) 351 return std::error_code(errno, std::generic_category()); 352 353 if (Mode == AccessMode::Execute) { 354 // Don't say that directories are executable. 355 struct stat buf; 356 if (0 != stat(P.begin(), &buf)) 357 return errc::permission_denied; 358 if (!S_ISREG(buf.st_mode)) 359 return errc::permission_denied; 360 } 361 362 return std::error_code(); 363} 364 365bool can_execute(const Twine &Path) { 366 return !access(Path, AccessMode::Execute); 367} 368 369bool equivalent(file_status A, file_status B) { 370 assert(status_known(A) && status_known(B)); 371 return A.fs_st_dev == B.fs_st_dev && 372 A.fs_st_ino == B.fs_st_ino; 373} 374 375std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { 376 file_status fsA, fsB; 377 if (std::error_code ec = status(A, fsA)) 378 return ec; 379 if (std::error_code ec = status(B, fsB)) 380 return ec; 381 result = equivalent(fsA, fsB); 382 return std::error_code(); 383} 384 385static std::error_code fillStatus(int StatRet, const struct stat &Status, 386 file_status &Result) { 387 if (StatRet != 0) { 388 std::error_code ec(errno, std::generic_category()); 389 if (ec == errc::no_such_file_or_directory) 390 Result = file_status(file_type::file_not_found); 391 else 392 Result = file_status(file_type::status_error); 393 return ec; 394 } 395 396 file_type Type = file_type::type_unknown; 397 398 if (S_ISDIR(Status.st_mode)) 399 Type = file_type::directory_file; 400 else if (S_ISREG(Status.st_mode)) 401 Type = file_type::regular_file; 402 else if (S_ISBLK(Status.st_mode)) 403 Type = file_type::block_file; 404 else if (S_ISCHR(Status.st_mode)) 405 Type = file_type::character_file; 406 else if (S_ISFIFO(Status.st_mode)) 407 Type = file_type::fifo_file; 408 else if (S_ISSOCK(Status.st_mode)) 409 Type = file_type::socket_file; 410 411 perms Perms = static_cast<perms>(Status.st_mode); 412 Result = 413 file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_atime, 414 Status.st_mtime, Status.st_uid, Status.st_gid, 415 Status.st_size); 416 417 return std::error_code(); 418} 419 420std::error_code status(const Twine &Path, file_status &Result) { 421 SmallString<128> PathStorage; 422 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 423 424 struct stat Status; 425 int StatRet = ::stat(P.begin(), &Status); 426 return fillStatus(StatRet, Status, Result); 427} 428 429std::error_code status(int FD, file_status &Result) { 430 struct stat Status; 431 int StatRet = ::fstat(FD, &Status); 432 return fillStatus(StatRet, Status, Result); 433} 434 435std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { 436#if defined(HAVE_FUTIMENS) 437 timespec Times[2]; 438 Times[0].tv_sec = Time.toEpochTime(); 439 Times[0].tv_nsec = 0; 440 Times[1] = Times[0]; 441 if (::futimens(FD, Times)) 442 return std::error_code(errno, std::generic_category()); 443 return std::error_code(); 444#elif defined(HAVE_FUTIMES) 445 timeval Times[2]; 446 Times[0].tv_sec = Time.toEpochTime(); 447 Times[0].tv_usec = 0; 448 Times[1] = Times[0]; 449 if (::futimes(FD, Times)) 450 return std::error_code(errno, std::generic_category()); 451 return std::error_code(); 452#else 453#warning Missing futimes() and futimens() 454 return make_error_code(errc::function_not_supported); 455#endif 456} 457 458std::error_code mapped_file_region::init(int FD, uint64_t Offset, 459 mapmode Mode) { 460 assert(Size != 0); 461 462 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; 463 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); 464 Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset); 465 if (Mapping == MAP_FAILED) 466 return std::error_code(errno, std::generic_category()); 467 return std::error_code(); 468} 469 470mapped_file_region::mapped_file_region(int fd, mapmode mode, uint64_t length, 471 uint64_t offset, std::error_code &ec) 472 : Size(length), Mapping() { 473 // Make sure that the requested size fits within SIZE_T. 474 if (length > std::numeric_limits<size_t>::max()) { 475 ec = make_error_code(errc::invalid_argument); 476 return; 477 } 478 479 ec = init(fd, offset, mode); 480 if (ec) 481 Mapping = nullptr; 482} 483 484mapped_file_region::~mapped_file_region() { 485 if (Mapping) 486 ::munmap(Mapping, Size); 487} 488 489uint64_t mapped_file_region::size() const { 490 assert(Mapping && "Mapping failed but used anyway!"); 491 return Size; 492} 493 494char *mapped_file_region::data() const { 495 assert(Mapping && "Mapping failed but used anyway!"); 496 return reinterpret_cast<char*>(Mapping); 497} 498 499const char *mapped_file_region::const_data() const { 500 assert(Mapping && "Mapping failed but used anyway!"); 501 return reinterpret_cast<const char*>(Mapping); 502} 503 504int mapped_file_region::alignment() { 505 return Process::getPageSize(); 506} 507 508std::error_code detail::directory_iterator_construct(detail::DirIterState &it, 509 StringRef path){ 510 SmallString<128> path_null(path); 511 DIR *directory = ::opendir(path_null.c_str()); 512 if (!directory) 513 return std::error_code(errno, std::generic_category()); 514 515 it.IterationHandle = reinterpret_cast<intptr_t>(directory); 516 // Add something for replace_filename to replace. 517 path::append(path_null, "."); 518 it.CurrentEntry = directory_entry(path_null.str()); 519 return directory_iterator_increment(it); 520} 521 522std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { 523 if (it.IterationHandle) 524 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle)); 525 it.IterationHandle = 0; 526 it.CurrentEntry = directory_entry(); 527 return std::error_code(); 528} 529 530std::error_code detail::directory_iterator_increment(detail::DirIterState &it) { 531 errno = 0; 532 dirent *cur_dir = ::readdir(reinterpret_cast<DIR *>(it.IterationHandle)); 533 if (cur_dir == nullptr && errno != 0) { 534 return std::error_code(errno, std::generic_category()); 535 } else if (cur_dir != nullptr) { 536 StringRef name(cur_dir->d_name, NAMLEN(cur_dir)); 537 if ((name.size() == 1 && name[0] == '.') || 538 (name.size() == 2 && name[0] == '.' && name[1] == '.')) 539 return directory_iterator_increment(it); 540 it.CurrentEntry.replace_filename(name); 541 } else 542 return directory_iterator_destruct(it); 543 544 return std::error_code(); 545} 546 547std::error_code openFileForRead(const Twine &Name, int &ResultFD) { 548 SmallString<128> Storage; 549 StringRef P = Name.toNullTerminatedStringRef(Storage); 550 while ((ResultFD = open(P.begin(), O_RDONLY)) < 0) { 551 if (errno != EINTR) 552 return std::error_code(errno, std::generic_category()); 553 } 554 return std::error_code(); 555} 556 557std::error_code openFileForWrite(const Twine &Name, int &ResultFD, 558 sys::fs::OpenFlags Flags, unsigned Mode) { 559 // Verify that we don't have both "append" and "excl". 560 assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) && 561 "Cannot specify both 'excl' and 'append' file creation flags!"); 562 563 int OpenFlags = O_CREAT; 564 565 if (Flags & F_RW) 566 OpenFlags |= O_RDWR; 567 else 568 OpenFlags |= O_WRONLY; 569 570 if (Flags & F_Append) 571 OpenFlags |= O_APPEND; 572 else 573 OpenFlags |= O_TRUNC; 574 575 if (Flags & F_Excl) 576 OpenFlags |= O_EXCL; 577 578 SmallString<128> Storage; 579 StringRef P = Name.toNullTerminatedStringRef(Storage); 580 while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) { 581 if (errno != EINTR) 582 return std::error_code(errno, std::generic_category()); 583 } 584 return std::error_code(); 585} 586 587} // end namespace fs 588 589namespace path { 590 591bool home_directory(SmallVectorImpl<char> &result) { 592 if (char *RequestedDir = getenv("HOME")) { 593 result.clear(); 594 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 595 return true; 596 } 597 598 return false; 599} 600 601static bool getDarwinConfDir(bool TempDir, SmallVectorImpl<char> &Result) { 602 #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) 603 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. 604 // macros defined in <unistd.h> on darwin >= 9 605 int ConfName = TempDir ? _CS_DARWIN_USER_TEMP_DIR 606 : _CS_DARWIN_USER_CACHE_DIR; 607 size_t ConfLen = confstr(ConfName, nullptr, 0); 608 if (ConfLen > 0) { 609 do { 610 Result.resize(ConfLen); 611 ConfLen = confstr(ConfName, Result.data(), Result.size()); 612 } while (ConfLen > 0 && ConfLen != Result.size()); 613 614 if (ConfLen > 0) { 615 assert(Result.back() == 0); 616 Result.pop_back(); 617 return true; 618 } 619 620 Result.clear(); 621 } 622 #endif 623 return false; 624} 625 626static bool getUserCacheDir(SmallVectorImpl<char> &Result) { 627 // First try using XDG_CACHE_HOME env variable, 628 // as specified in XDG Base Directory Specification at 629 // http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html 630 if (const char *XdgCacheDir = std::getenv("XDG_CACHE_HOME")) { 631 Result.clear(); 632 Result.append(XdgCacheDir, XdgCacheDir + strlen(XdgCacheDir)); 633 return true; 634 } 635 636 // Try Darwin configuration query 637 if (getDarwinConfDir(false, Result)) 638 return true; 639 640 // Use "$HOME/.cache" if $HOME is available 641 if (home_directory(Result)) { 642 append(Result, ".cache"); 643 return true; 644 } 645 646 return false; 647} 648 649static const char *getEnvTempDir() { 650 // Check whether the temporary directory is specified by an environment 651 // variable. 652 const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; 653 for (const char *Env : EnvironmentVariables) { 654 if (const char *Dir = std::getenv(Env)) 655 return Dir; 656 } 657 658 return nullptr; 659} 660 661static const char *getDefaultTempDir(bool ErasedOnReboot) { 662#ifdef P_tmpdir 663 if ((bool)P_tmpdir) 664 return P_tmpdir; 665#endif 666 667 if (ErasedOnReboot) 668 return "/tmp"; 669 return "/var/tmp"; 670} 671 672void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { 673 Result.clear(); 674 675 if (ErasedOnReboot) { 676 // There is no env variable for the cache directory. 677 if (const char *RequestedDir = getEnvTempDir()) { 678 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 679 return; 680 } 681 } 682 683 if (getDarwinConfDir(ErasedOnReboot, Result)) 684 return; 685 686 const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); 687 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 688} 689 690} // end namespace path 691 692} // end namespace sys 693} // end namespace llvm 694