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 "llvm/Support/Process.h" 21 #include <limits.h> 22 #include <stdio.h> 23 #if HAVE_SYS_STAT_H 24 #include <sys/stat.h> 25 #endif 26 #if HAVE_FCNTL_H 27 #include <fcntl.h> 28 #endif 29 #ifdef HAVE_SYS_MMAN_H 30 #include <sys/mman.h> 31 #endif 32 #if HAVE_DIRENT_H 33 # include <dirent.h> 34 # define NAMLEN(dirent) strlen((dirent)->d_name) 35 #else 36 # define dirent direct 37 # define NAMLEN(dirent) (dirent)->d_namlen 38 # if HAVE_SYS_NDIR_H 39 # include <sys/ndir.h> 40 # endif 41 # if HAVE_SYS_DIR_H 42 # include <sys/dir.h> 43 # endif 44 # if HAVE_NDIR_H 45 # include <ndir.h> 46 # endif 47 #endif 48 49 #ifdef __APPLE__ 50 #include <mach-o/dyld.h> 51 #endif 52 53 // Both stdio.h and cstdio are included via different pathes and 54 // stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros 55 // either. 56 #undef ferror 57 #undef feof 58 59 // For GNU Hurd 60 #if defined(__GNU__) && !defined(PATH_MAX) 61 # define PATH_MAX 4096 62 #endif 63 64 using namespace llvm; 65 66 namespace { 67 /// This class automatically closes the given file descriptor when it goes out 68 /// of scope. You can take back explicit ownership of the file descriptor by 69 /// calling take(). The destructor does not verify that close was successful. 70 /// Therefore, never allow this class to call close on a file descriptor that 71 /// has been read from or written to. 72 struct AutoFD { 73 int FileDescriptor; 74 75 AutoFD(int fd) : FileDescriptor(fd) {} 76 ~AutoFD() { 77 if (FileDescriptor >= 0) 78 ::close(FileDescriptor); 79 } 80 81 int take() { 82 int ret = FileDescriptor; 83 FileDescriptor = -1; 84 return ret; 85 } 86 87 operator int() const {return FileDescriptor;} 88 }; 89 90 error_code TempDir(SmallVectorImpl<char> &result) { 91 // FIXME: Don't use TMPDIR if program is SUID or SGID enabled. 92 const char *dir = 0; 93 (dir = std::getenv("TMPDIR" )) || 94 (dir = std::getenv("TMP" )) || 95 (dir = std::getenv("TEMP" )) || 96 (dir = std::getenv("TEMPDIR")) || 97 #ifdef P_tmpdir 98 (dir = P_tmpdir) || 99 #endif 100 (dir = "/tmp"); 101 102 result.clear(); 103 StringRef d(dir); 104 result.append(d.begin(), d.end()); 105 return error_code::success(); 106 } 107 } 108 109 static error_code createUniqueEntity(const Twine &Model, int &ResultFD, 110 SmallVectorImpl<char> &ResultPath, 111 bool MakeAbsolute, unsigned Mode, 112 FSEntity Type) { 113 SmallString<128> ModelStorage; 114 Model.toVector(ModelStorage); 115 116 if (MakeAbsolute) { 117 // Make model absolute by prepending a temp directory if it's not already. 118 bool absolute = sys::path::is_absolute(Twine(ModelStorage)); 119 if (!absolute) { 120 SmallString<128> TDir; 121 if (error_code ec = TempDir(TDir)) return ec; 122 sys::path::append(TDir, Twine(ModelStorage)); 123 ModelStorage.swap(TDir); 124 } 125 } 126 127 // From here on, DO NOT modify model. It may be needed if the randomly chosen 128 // path already exists. 129 ResultPath = ModelStorage; 130 // Null terminate. 131 ResultPath.push_back(0); 132 ResultPath.pop_back(); 133 134 retry_random_path: 135 // Replace '%' with random chars. 136 for (unsigned i = 0, e = ModelStorage.size(); i != e; ++i) { 137 if (ModelStorage[i] == '%') 138 ResultPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; 139 } 140 141 // Try to open + create the file. 142 switch (Type) { 143 case FS_File: { 144 int RandomFD = ::open(ResultPath.begin(), O_RDWR | O_CREAT | O_EXCL, Mode); 145 if (RandomFD == -1) { 146 int SavedErrno = errno; 147 // If the file existed, try again, otherwise, error. 148 if (SavedErrno == errc::file_exists) 149 goto retry_random_path; 150 return error_code(SavedErrno, system_category()); 151 } 152 153 ResultFD = RandomFD; 154 return error_code::success(); 155 } 156 157 case FS_Name: { 158 bool Exists; 159 error_code EC = sys::fs::exists(ResultPath.begin(), Exists); 160 if (EC) 161 return EC; 162 if (Exists) 163 goto retry_random_path; 164 return error_code::success(); 165 } 166 167 case FS_Dir: { 168 bool Existed; 169 error_code EC = sys::fs::create_directory(ResultPath.begin(), Existed); 170 if (EC) 171 return EC; 172 if (Existed) 173 goto retry_random_path; 174 return error_code::success(); 175 } 176 } 177 llvm_unreachable("Invalid Type"); 178 } 179 180 namespace llvm { 181 namespace sys { 182 namespace fs { 183 #if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 184 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \ 185 defined(__linux__) || defined(__CYGWIN__) 186 static int 187 test_dir(char buf[PATH_MAX], char ret[PATH_MAX], 188 const char *dir, const char *bin) 189 { 190 struct stat sb; 191 192 snprintf(buf, PATH_MAX, "%s/%s", dir, bin); 193 if (realpath(buf, ret) == NULL) 194 return (1); 195 if (stat(buf, &sb) != 0) 196 return (1); 197 198 return (0); 199 } 200 201 static char * 202 getprogpath(char ret[PATH_MAX], const char *bin) 203 { 204 char *pv, *s, *t, buf[PATH_MAX]; 205 206 /* First approach: absolute path. */ 207 if (bin[0] == '/') { 208 if (test_dir(buf, ret, "/", bin) == 0) 209 return (ret); 210 return (NULL); 211 } 212 213 /* Second approach: relative path. */ 214 if (strchr(bin, '/') != NULL) { 215 if (getcwd(buf, PATH_MAX) == NULL) 216 return (NULL); 217 if (test_dir(buf, ret, buf, bin) == 0) 218 return (ret); 219 return (NULL); 220 } 221 222 /* Third approach: $PATH */ 223 if ((pv = getenv("PATH")) == NULL) 224 return (NULL); 225 s = pv = strdup(pv); 226 if (pv == NULL) 227 return (NULL); 228 while ((t = strsep(&s, ":")) != NULL) { 229 if (test_dir(buf, ret, t, bin) == 0) { 230 free(pv); 231 return (ret); 232 } 233 } 234 free(pv); 235 return (NULL); 236 } 237 #endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ 238 239 /// GetMainExecutable - Return the path to the main executable, given the 240 /// value of argv[0] from program startup. 241 std::string getMainExecutable(const char *argv0, void *MainAddr) { 242 #if defined(__APPLE__) 243 // On OS X the executable path is saved to the stack by dyld. Reading it 244 // from there is much faster than calling dladdr, especially for large 245 // binaries with symbols. 246 char exe_path[MAXPATHLEN]; 247 uint32_t size = sizeof(exe_path); 248 if (_NSGetExecutablePath(exe_path, &size) == 0) { 249 char link_path[MAXPATHLEN]; 250 if (realpath(exe_path, link_path)) 251 return link_path; 252 } 253 #elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 254 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) 255 char exe_path[PATH_MAX]; 256 257 if (getprogpath(exe_path, argv0) != NULL) 258 return exe_path; 259 #elif defined(__linux__) || defined(__CYGWIN__) 260 char exe_path[MAXPATHLEN]; 261 StringRef aPath("/proc/self/exe"); 262 if (sys::fs::exists(aPath)) { 263 // /proc is not always mounted under Linux (chroot for example). 264 ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); 265 if (len >= 0) 266 return StringRef(exe_path, len); 267 } else { 268 // Fall back to the classical detection. 269 if (getprogpath(exe_path, argv0) != NULL) 270 return exe_path; 271 } 272 #elif defined(HAVE_DLFCN_H) 273 // Use dladdr to get executable path if available. 274 Dl_info DLInfo; 275 int err = dladdr(MainAddr, &DLInfo); 276 if (err == 0) 277 return ""; 278 279 // If the filename is a symlink, we need to resolve and return the location of 280 // the actual executable. 281 char link_path[MAXPATHLEN]; 282 if (realpath(DLInfo.dli_fname, link_path)) 283 return link_path; 284 #else 285 #error GetMainExecutable is not implemented on this host yet. 286 #endif 287 return ""; 288 } 289 290 TimeValue file_status::getLastModificationTime() const { 291 TimeValue Ret; 292 Ret.fromEpochTime(fs_st_mtime); 293 return Ret; 294 } 295 296 UniqueID file_status::getUniqueID() const { 297 return UniqueID(fs_st_dev, fs_st_ino); 298 } 299 300 error_code current_path(SmallVectorImpl<char> &result) { 301 #ifdef MAXPATHLEN 302 result.reserve(MAXPATHLEN); 303 #else 304 // For GNU Hurd 305 result.reserve(1024); 306 #endif 307 308 while (true) { 309 if (::getcwd(result.data(), result.capacity()) == 0) { 310 // See if there was a real error. 311 if (errno != errc::not_enough_memory) 312 return error_code(errno, system_category()); 313 // Otherwise there just wasn't enough space. 314 result.reserve(result.capacity() * 2); 315 } else 316 break; 317 } 318 319 result.set_size(strlen(result.data())); 320 return error_code::success(); 321 } 322 323 error_code create_directory(const Twine &path, bool &existed) { 324 SmallString<128> path_storage; 325 StringRef p = path.toNullTerminatedStringRef(path_storage); 326 327 if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) { 328 if (errno != errc::file_exists) 329 return error_code(errno, system_category()); 330 existed = true; 331 } else 332 existed = false; 333 334 return error_code::success(); 335 } 336 337 error_code create_hard_link(const Twine &to, const Twine &from) { 338 // Get arguments. 339 SmallString<128> from_storage; 340 SmallString<128> to_storage; 341 StringRef f = from.toNullTerminatedStringRef(from_storage); 342 StringRef t = to.toNullTerminatedStringRef(to_storage); 343 344 if (::link(t.begin(), f.begin()) == -1) 345 return error_code(errno, system_category()); 346 347 return error_code::success(); 348 } 349 350 error_code create_symlink(const Twine &to, const Twine &from) { 351 // Get arguments. 352 SmallString<128> from_storage; 353 SmallString<128> to_storage; 354 StringRef f = from.toNullTerminatedStringRef(from_storage); 355 StringRef t = to.toNullTerminatedStringRef(to_storage); 356 357 if (::symlink(t.begin(), f.begin()) == -1) 358 return error_code(errno, system_category()); 359 360 return error_code::success(); 361 } 362 363 error_code remove(const Twine &path, bool &existed) { 364 SmallString<128> path_storage; 365 StringRef p = path.toNullTerminatedStringRef(path_storage); 366 367 struct stat buf; 368 if (stat(p.begin(), &buf) != 0) { 369 if (errno != errc::no_such_file_or_directory) 370 return error_code(errno, system_category()); 371 existed = false; 372 return error_code::success(); 373 } 374 375 // Note: this check catches strange situations. In all cases, LLVM should 376 // only be involved in the creation and deletion of regular files. This 377 // check ensures that what we're trying to erase is a regular file. It 378 // effectively prevents LLVM from erasing things like /dev/null, any block 379 // special file, or other things that aren't "regular" files. 380 if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode)) 381 return make_error_code(errc::operation_not_permitted); 382 383 if (::remove(p.begin()) == -1) { 384 if (errno != errc::no_such_file_or_directory) 385 return error_code(errno, system_category()); 386 existed = false; 387 } else 388 existed = true; 389 390 return error_code::success(); 391 } 392 393 error_code rename(const Twine &from, const Twine &to) { 394 // Get arguments. 395 SmallString<128> from_storage; 396 SmallString<128> to_storage; 397 StringRef f = from.toNullTerminatedStringRef(from_storage); 398 StringRef t = to.toNullTerminatedStringRef(to_storage); 399 400 if (::rename(f.begin(), t.begin()) == -1) 401 return error_code(errno, system_category()); 402 403 return error_code::success(); 404 } 405 406 error_code resize_file(const Twine &path, uint64_t size) { 407 SmallString<128> path_storage; 408 StringRef p = path.toNullTerminatedStringRef(path_storage); 409 410 if (::truncate(p.begin(), size) == -1) 411 return error_code(errno, system_category()); 412 413 return error_code::success(); 414 } 415 416 error_code exists(const Twine &path, bool &result) { 417 SmallString<128> path_storage; 418 StringRef p = path.toNullTerminatedStringRef(path_storage); 419 420 if (::access(p.begin(), F_OK) == -1) { 421 if (errno != errc::no_such_file_or_directory) 422 return error_code(errno, system_category()); 423 result = false; 424 } else 425 result = true; 426 427 return error_code::success(); 428 } 429 430 bool can_write(const Twine &Path) { 431 SmallString<128> PathStorage; 432 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 433 return 0 == access(P.begin(), W_OK); 434 } 435 436 bool can_execute(const Twine &Path) { 437 SmallString<128> PathStorage; 438 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 439 440 if (0 != access(P.begin(), R_OK | X_OK)) 441 return false; 442 struct stat buf; 443 if (0 != stat(P.begin(), &buf)) 444 return false; 445 if (!S_ISREG(buf.st_mode)) 446 return false; 447 return true; 448 } 449 450 bool equivalent(file_status A, file_status B) { 451 assert(status_known(A) && status_known(B)); 452 return A.fs_st_dev == B.fs_st_dev && 453 A.fs_st_ino == B.fs_st_ino; 454 } 455 456 error_code equivalent(const Twine &A, const Twine &B, bool &result) { 457 file_status fsA, fsB; 458 if (error_code ec = status(A, fsA)) return ec; 459 if (error_code ec = status(B, fsB)) return ec; 460 result = equivalent(fsA, fsB); 461 return error_code::success(); 462 } 463 464 static error_code fillStatus(int StatRet, const struct stat &Status, 465 file_status &Result) { 466 if (StatRet != 0) { 467 error_code ec(errno, system_category()); 468 if (ec == errc::no_such_file_or_directory) 469 Result = file_status(file_type::file_not_found); 470 else 471 Result = file_status(file_type::status_error); 472 return ec; 473 } 474 475 file_type Type = file_type::type_unknown; 476 477 if (S_ISDIR(Status.st_mode)) 478 Type = file_type::directory_file; 479 else if (S_ISREG(Status.st_mode)) 480 Type = file_type::regular_file; 481 else if (S_ISBLK(Status.st_mode)) 482 Type = file_type::block_file; 483 else if (S_ISCHR(Status.st_mode)) 484 Type = file_type::character_file; 485 else if (S_ISFIFO(Status.st_mode)) 486 Type = file_type::fifo_file; 487 else if (S_ISSOCK(Status.st_mode)) 488 Type = file_type::socket_file; 489 490 perms Perms = static_cast<perms>(Status.st_mode); 491 Result = 492 file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_mtime, 493 Status.st_uid, Status.st_gid, Status.st_size); 494 495 return error_code::success(); 496 } 497 498 error_code status(const Twine &Path, file_status &Result) { 499 SmallString<128> PathStorage; 500 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 501 502 struct stat Status; 503 int StatRet = ::stat(P.begin(), &Status); 504 return fillStatus(StatRet, Status, Result); 505 } 506 507 error_code status(int FD, file_status &Result) { 508 struct stat Status; 509 int StatRet = ::fstat(FD, &Status); 510 return fillStatus(StatRet, Status, Result); 511 } 512 513 error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { 514 #if defined(HAVE_FUTIMENS) 515 timespec Times[2]; 516 Times[0].tv_sec = Time.toPosixTime(); 517 Times[0].tv_nsec = 0; 518 Times[1] = Times[0]; 519 if (::futimens(FD, Times)) 520 #elif defined(HAVE_FUTIMES) 521 timeval Times[2]; 522 Times[0].tv_sec = Time.toPosixTime(); 523 Times[0].tv_usec = 0; 524 Times[1] = Times[0]; 525 if (::futimes(FD, Times)) 526 #else 527 #error Missing futimes() and futimens() 528 #endif 529 return error_code(errno, system_category()); 530 return error_code::success(); 531 } 532 533 error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) { 534 AutoFD ScopedFD(FD); 535 if (!CloseFD) 536 ScopedFD.take(); 537 538 // Figure out how large the file is. 539 struct stat FileInfo; 540 if (fstat(FD, &FileInfo) == -1) 541 return error_code(errno, system_category()); 542 uint64_t FileSize = FileInfo.st_size; 543 544 if (Size == 0) 545 Size = FileSize; 546 else if (FileSize < Size) { 547 // We need to grow the file. 548 if (ftruncate(FD, Size) == -1) 549 return error_code(errno, system_category()); 550 } 551 552 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; 553 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); 554 #ifdef MAP_FILE 555 flags |= MAP_FILE; 556 #endif 557 Mapping = ::mmap(0, Size, prot, flags, FD, Offset); 558 if (Mapping == MAP_FAILED) 559 return error_code(errno, system_category()); 560 return error_code::success(); 561 } 562 563 mapped_file_region::mapped_file_region(const Twine &path, 564 mapmode mode, 565 uint64_t length, 566 uint64_t offset, 567 error_code &ec) 568 : Mode(mode) 569 , Size(length) 570 , Mapping() { 571 // Make sure that the requested size fits within SIZE_T. 572 if (length > std::numeric_limits<size_t>::max()) { 573 ec = make_error_code(errc::invalid_argument); 574 return; 575 } 576 577 SmallString<128> path_storage; 578 StringRef name = path.toNullTerminatedStringRef(path_storage); 579 int oflags = (mode == readonly) ? O_RDONLY : O_RDWR; 580 int ofd = ::open(name.begin(), oflags); 581 if (ofd == -1) { 582 ec = error_code(errno, system_category()); 583 return; 584 } 585 586 ec = init(ofd, true, offset); 587 if (ec) 588 Mapping = 0; 589 } 590 591 mapped_file_region::mapped_file_region(int fd, 592 bool closefd, 593 mapmode mode, 594 uint64_t length, 595 uint64_t offset, 596 error_code &ec) 597 : Mode(mode) 598 , Size(length) 599 , Mapping() { 600 // Make sure that the requested size fits within SIZE_T. 601 if (length > std::numeric_limits<size_t>::max()) { 602 ec = make_error_code(errc::invalid_argument); 603 return; 604 } 605 606 ec = init(fd, closefd, offset); 607 if (ec) 608 Mapping = 0; 609 } 610 611 mapped_file_region::~mapped_file_region() { 612 if (Mapping) 613 ::munmap(Mapping, Size); 614 } 615 616 #if LLVM_HAS_RVALUE_REFERENCES 617 mapped_file_region::mapped_file_region(mapped_file_region &&other) 618 : Mode(other.Mode), Size(other.Size), Mapping(other.Mapping) { 619 other.Mapping = 0; 620 } 621 #endif 622 623 mapped_file_region::mapmode mapped_file_region::flags() const { 624 assert(Mapping && "Mapping failed but used anyway!"); 625 return Mode; 626 } 627 628 uint64_t mapped_file_region::size() const { 629 assert(Mapping && "Mapping failed but used anyway!"); 630 return Size; 631 } 632 633 char *mapped_file_region::data() const { 634 assert(Mapping && "Mapping failed but used anyway!"); 635 assert(Mode != readonly && "Cannot get non const data for readonly mapping!"); 636 return reinterpret_cast<char*>(Mapping); 637 } 638 639 const char *mapped_file_region::const_data() const { 640 assert(Mapping && "Mapping failed but used anyway!"); 641 return reinterpret_cast<const char*>(Mapping); 642 } 643 644 int mapped_file_region::alignment() { 645 return process::get_self()->page_size(); 646 } 647 648 error_code detail::directory_iterator_construct(detail::DirIterState &it, 649 StringRef path){ 650 SmallString<128> path_null(path); 651 DIR *directory = ::opendir(path_null.c_str()); 652 if (directory == 0) 653 return error_code(errno, system_category()); 654 655 it.IterationHandle = reinterpret_cast<intptr_t>(directory); 656 // Add something for replace_filename to replace. 657 path::append(path_null, "."); 658 it.CurrentEntry = directory_entry(path_null.str()); 659 return directory_iterator_increment(it); 660 } 661 662 error_code detail::directory_iterator_destruct(detail::DirIterState &it) { 663 if (it.IterationHandle) 664 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle)); 665 it.IterationHandle = 0; 666 it.CurrentEntry = directory_entry(); 667 return error_code::success(); 668 } 669 670 error_code detail::directory_iterator_increment(detail::DirIterState &it) { 671 errno = 0; 672 dirent *cur_dir = ::readdir(reinterpret_cast<DIR *>(it.IterationHandle)); 673 if (cur_dir == 0 && errno != 0) { 674 return error_code(errno, system_category()); 675 } else if (cur_dir != 0) { 676 StringRef name(cur_dir->d_name, NAMLEN(cur_dir)); 677 if ((name.size() == 1 && name[0] == '.') || 678 (name.size() == 2 && name[0] == '.' && name[1] == '.')) 679 return directory_iterator_increment(it); 680 it.CurrentEntry.replace_filename(name); 681 } else 682 return directory_iterator_destruct(it); 683 684 return error_code::success(); 685 } 686 687 error_code get_magic(const Twine &path, uint32_t len, 688 SmallVectorImpl<char> &result) { 689 SmallString<128> PathStorage; 690 StringRef Path = path.toNullTerminatedStringRef(PathStorage); 691 result.set_size(0); 692 693 // Open path. 694 std::FILE *file = std::fopen(Path.data(), "rb"); 695 if (file == 0) 696 return error_code(errno, system_category()); 697 698 // Reserve storage. 699 result.reserve(len); 700 701 // Read magic! 702 size_t size = std::fread(result.data(), 1, len, file); 703 if (std::ferror(file) != 0) { 704 std::fclose(file); 705 return error_code(errno, system_category()); 706 } else if (size != len) { 707 if (std::feof(file) != 0) { 708 std::fclose(file); 709 result.set_size(size); 710 return make_error_code(errc::value_too_large); 711 } 712 } 713 std::fclose(file); 714 result.set_size(size); 715 return error_code::success(); 716 } 717 718 error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, 719 bool map_writable, void *&result) { 720 SmallString<128> path_storage; 721 StringRef name = path.toNullTerminatedStringRef(path_storage); 722 int oflags = map_writable ? O_RDWR : O_RDONLY; 723 int ofd = ::open(name.begin(), oflags); 724 if ( ofd == -1 ) 725 return error_code(errno, system_category()); 726 AutoFD fd(ofd); 727 int flags = map_writable ? MAP_SHARED : MAP_PRIVATE; 728 int prot = map_writable ? (PROT_READ|PROT_WRITE) : PROT_READ; 729 #ifdef MAP_FILE 730 flags |= MAP_FILE; 731 #endif 732 result = ::mmap(0, size, prot, flags, fd, file_offset); 733 if (result == MAP_FAILED) { 734 return error_code(errno, system_category()); 735 } 736 737 return error_code::success(); 738 } 739 740 error_code unmap_file_pages(void *base, size_t size) { 741 if ( ::munmap(base, size) == -1 ) 742 return error_code(errno, system_category()); 743 744 return error_code::success(); 745 } 746 747 error_code openFileForRead(const Twine &Name, int &ResultFD) { 748 SmallString<128> Storage; 749 StringRef P = Name.toNullTerminatedStringRef(Storage); 750 while ((ResultFD = open(P.begin(), O_RDONLY)) < 0) { 751 if (errno != EINTR) 752 return error_code(errno, system_category()); 753 } 754 return error_code::success(); 755 } 756 757 error_code openFileForWrite(const Twine &Name, int &ResultFD, 758 sys::fs::OpenFlags Flags, unsigned Mode) { 759 // Verify that we don't have both "append" and "excl". 760 assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) && 761 "Cannot specify both 'excl' and 'append' file creation flags!"); 762 763 int OpenFlags = O_WRONLY | O_CREAT; 764 765 if (Flags & F_Append) 766 OpenFlags |= O_APPEND; 767 else 768 OpenFlags |= O_TRUNC; 769 770 if (Flags & F_Excl) 771 OpenFlags |= O_EXCL; 772 773 SmallString<128> Storage; 774 StringRef P = Name.toNullTerminatedStringRef(Storage); 775 while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) { 776 if (errno != EINTR) 777 return error_code(errno, system_category()); 778 } 779 return error_code::success(); 780 } 781 782 } // end namespace fs 783 } // end namespace sys 784 } // end namespace llvm 785