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