LLVM API Documentation
00001 //===- llvm/Support/Unix/Path.inc - Unix Path Implementation ----*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the Unix specific implementation of the Path API. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 //===----------------------------------------------------------------------===// 00015 //=== WARNING: Implementation here must contain only generic UNIX code that 00016 //=== is guaranteed to work on *all* UNIX variants. 00017 //===----------------------------------------------------------------------===// 00018 00019 #include "Unix.h" 00020 #include <limits.h> 00021 #include <stdio.h> 00022 #if HAVE_SYS_STAT_H 00023 #include <sys/stat.h> 00024 #endif 00025 #if HAVE_FCNTL_H 00026 #include <fcntl.h> 00027 #endif 00028 #ifdef HAVE_SYS_MMAN_H 00029 #include <sys/mman.h> 00030 #endif 00031 #if HAVE_DIRENT_H 00032 # include <dirent.h> 00033 # define NAMLEN(dirent) strlen((dirent)->d_name) 00034 #else 00035 # define dirent direct 00036 # define NAMLEN(dirent) (dirent)->d_namlen 00037 # if HAVE_SYS_NDIR_H 00038 # include <sys/ndir.h> 00039 # endif 00040 # if HAVE_SYS_DIR_H 00041 # include <sys/dir.h> 00042 # endif 00043 # if HAVE_NDIR_H 00044 # include <ndir.h> 00045 # endif 00046 #endif 00047 00048 #ifdef __APPLE__ 00049 #include <mach-o/dyld.h> 00050 #endif 00051 00052 // Both stdio.h and cstdio are included via different pathes and 00053 // stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros 00054 // either. 00055 #undef ferror 00056 #undef feof 00057 00058 // For GNU Hurd 00059 #if defined(__GNU__) && !defined(PATH_MAX) 00060 # define PATH_MAX 4096 00061 #endif 00062 00063 using namespace llvm; 00064 00065 namespace { 00066 /// This class automatically closes the given file descriptor when it goes out 00067 /// of scope. You can take back explicit ownership of the file descriptor by 00068 /// calling take(). The destructor does not verify that close was successful. 00069 /// Therefore, never allow this class to call close on a file descriptor that 00070 /// has been read from or written to. 00071 struct AutoFD { 00072 int FileDescriptor; 00073 00074 AutoFD(int fd) : FileDescriptor(fd) {} 00075 ~AutoFD() { 00076 if (FileDescriptor >= 0) 00077 ::close(FileDescriptor); 00078 } 00079 00080 int take() { 00081 int ret = FileDescriptor; 00082 FileDescriptor = -1; 00083 return ret; 00084 } 00085 00086 operator int() const {return FileDescriptor;} 00087 }; 00088 } 00089 00090 namespace llvm { 00091 namespace sys { 00092 namespace fs { 00093 #if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 00094 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \ 00095 defined(__linux__) || defined(__CYGWIN__) || defined(__DragonFly__) 00096 static int 00097 test_dir(char ret[PATH_MAX], const char *dir, const char *bin) 00098 { 00099 struct stat sb; 00100 char fullpath[PATH_MAX]; 00101 00102 snprintf(fullpath, PATH_MAX, "%s/%s", dir, bin); 00103 if (realpath(fullpath, ret) == NULL) 00104 return (1); 00105 if (stat(fullpath, &sb) != 0) 00106 return (1); 00107 00108 return (0); 00109 } 00110 00111 static char * 00112 getprogpath(char ret[PATH_MAX], const char *bin) 00113 { 00114 char *pv, *s, *t; 00115 00116 /* First approach: absolute path. */ 00117 if (bin[0] == '/') { 00118 if (test_dir(ret, "/", bin) == 0) 00119 return (ret); 00120 return (NULL); 00121 } 00122 00123 /* Second approach: relative path. */ 00124 if (strchr(bin, '/') != NULL) { 00125 char cwd[PATH_MAX]; 00126 if (getcwd(cwd, PATH_MAX) == NULL) 00127 return (NULL); 00128 if (test_dir(ret, cwd, bin) == 0) 00129 return (ret); 00130 return (NULL); 00131 } 00132 00133 /* Third approach: $PATH */ 00134 if ((pv = getenv("PATH")) == NULL) 00135 return (NULL); 00136 s = pv = strdup(pv); 00137 if (pv == NULL) 00138 return (NULL); 00139 while ((t = strsep(&s, ":")) != NULL) { 00140 if (test_dir(ret, t, bin) == 0) { 00141 free(pv); 00142 return (ret); 00143 } 00144 } 00145 free(pv); 00146 return (NULL); 00147 } 00148 #endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ 00149 00150 /// GetMainExecutable - Return the path to the main executable, given the 00151 /// value of argv[0] from program startup. 00152 std::string getMainExecutable(const char *argv0, void *MainAddr) { 00153 #if defined(__APPLE__) 00154 // On OS X the executable path is saved to the stack by dyld. Reading it 00155 // from there is much faster than calling dladdr, especially for large 00156 // binaries with symbols. 00157 char exe_path[MAXPATHLEN]; 00158 uint32_t size = sizeof(exe_path); 00159 if (_NSGetExecutablePath(exe_path, &size) == 0) { 00160 char link_path[MAXPATHLEN]; 00161 if (realpath(exe_path, link_path)) 00162 return link_path; 00163 } 00164 #elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 00165 defined(__OpenBSD__) || defined(__minix) || defined(__DragonFly__) || \ 00166 defined(__FreeBSD_kernel__) 00167 char exe_path[PATH_MAX]; 00168 00169 if (getprogpath(exe_path, argv0) != NULL) 00170 return exe_path; 00171 #elif defined(__linux__) || defined(__CYGWIN__) 00172 char exe_path[MAXPATHLEN]; 00173 StringRef aPath("/proc/self/exe"); 00174 if (sys::fs::exists(aPath)) { 00175 // /proc is not always mounted under Linux (chroot for example). 00176 ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); 00177 if (len >= 0) 00178 return StringRef(exe_path, len); 00179 } else { 00180 // Fall back to the classical detection. 00181 if (getprogpath(exe_path, argv0) != NULL) 00182 return exe_path; 00183 } 00184 #elif defined(HAVE_DLFCN_H) 00185 // Use dladdr to get executable path if available. 00186 Dl_info DLInfo; 00187 int err = dladdr(MainAddr, &DLInfo); 00188 if (err == 0) 00189 return ""; 00190 00191 // If the filename is a symlink, we need to resolve and return the location of 00192 // the actual executable. 00193 char link_path[MAXPATHLEN]; 00194 if (realpath(DLInfo.dli_fname, link_path)) 00195 return link_path; 00196 #else 00197 #error GetMainExecutable is not implemented on this host yet. 00198 #endif 00199 return ""; 00200 } 00201 00202 TimeValue file_status::getLastModificationTime() const { 00203 TimeValue Ret; 00204 Ret.fromEpochTime(fs_st_mtime); 00205 return Ret; 00206 } 00207 00208 UniqueID file_status::getUniqueID() const { 00209 return UniqueID(fs_st_dev, fs_st_ino); 00210 } 00211 00212 std::error_code current_path(SmallVectorImpl<char> &result) { 00213 result.clear(); 00214 00215 const char *pwd = ::getenv("PWD"); 00216 llvm::sys::fs::file_status PWDStatus, DotStatus; 00217 if (pwd && llvm::sys::path::is_absolute(pwd) && 00218 !llvm::sys::fs::status(pwd, PWDStatus) && 00219 !llvm::sys::fs::status(".", DotStatus) && 00220 PWDStatus.getUniqueID() == DotStatus.getUniqueID()) { 00221 result.append(pwd, pwd + strlen(pwd)); 00222 return std::error_code(); 00223 } 00224 00225 #ifdef MAXPATHLEN 00226 result.reserve(MAXPATHLEN); 00227 #else 00228 // For GNU Hurd 00229 result.reserve(1024); 00230 #endif 00231 00232 while (true) { 00233 if (::getcwd(result.data(), result.capacity()) == nullptr) { 00234 // See if there was a real error. 00235 if (errno != ENOMEM) 00236 return std::error_code(errno, std::generic_category()); 00237 // Otherwise there just wasn't enough space. 00238 result.reserve(result.capacity() * 2); 00239 } else 00240 break; 00241 } 00242 00243 result.set_size(strlen(result.data())); 00244 return std::error_code(); 00245 } 00246 00247 std::error_code create_directory(const Twine &path, bool IgnoreExisting) { 00248 SmallString<128> path_storage; 00249 StringRef p = path.toNullTerminatedStringRef(path_storage); 00250 00251 if (::mkdir(p.begin(), S_IRWXU | S_IRWXG) == -1) { 00252 if (errno != EEXIST || !IgnoreExisting) 00253 return std::error_code(errno, std::generic_category()); 00254 } 00255 00256 return std::error_code(); 00257 } 00258 00259 // Note that we are using symbolic link because hard links are not supported by 00260 // all filesystems (SMB doesn't). 00261 std::error_code create_link(const Twine &to, const Twine &from) { 00262 // Get arguments. 00263 SmallString<128> from_storage; 00264 SmallString<128> to_storage; 00265 StringRef f = from.toNullTerminatedStringRef(from_storage); 00266 StringRef t = to.toNullTerminatedStringRef(to_storage); 00267 00268 if (::symlink(t.begin(), f.begin()) == -1) 00269 return std::error_code(errno, std::generic_category()); 00270 00271 return std::error_code(); 00272 } 00273 00274 std::error_code remove(const Twine &path, bool IgnoreNonExisting) { 00275 SmallString<128> path_storage; 00276 StringRef p = path.toNullTerminatedStringRef(path_storage); 00277 00278 struct stat buf; 00279 if (lstat(p.begin(), &buf) != 0) { 00280 if (errno != ENOENT || !IgnoreNonExisting) 00281 return std::error_code(errno, std::generic_category()); 00282 return std::error_code(); 00283 } 00284 00285 // Note: this check catches strange situations. In all cases, LLVM should 00286 // only be involved in the creation and deletion of regular files. This 00287 // check ensures that what we're trying to erase is a regular file. It 00288 // effectively prevents LLVM from erasing things like /dev/null, any block 00289 // special file, or other things that aren't "regular" files. 00290 if (!S_ISREG(buf.st_mode) && !S_ISDIR(buf.st_mode) && !S_ISLNK(buf.st_mode)) 00291 return make_error_code(errc::operation_not_permitted); 00292 00293 if (::remove(p.begin()) == -1) { 00294 if (errno != ENOENT || !IgnoreNonExisting) 00295 return std::error_code(errno, std::generic_category()); 00296 } 00297 00298 return std::error_code(); 00299 } 00300 00301 std::error_code rename(const Twine &from, const Twine &to) { 00302 // Get arguments. 00303 SmallString<128> from_storage; 00304 SmallString<128> to_storage; 00305 StringRef f = from.toNullTerminatedStringRef(from_storage); 00306 StringRef t = to.toNullTerminatedStringRef(to_storage); 00307 00308 if (::rename(f.begin(), t.begin()) == -1) 00309 return std::error_code(errno, std::generic_category()); 00310 00311 return std::error_code(); 00312 } 00313 00314 std::error_code resize_file(const Twine &path, uint64_t size) { 00315 SmallString<128> path_storage; 00316 StringRef p = path.toNullTerminatedStringRef(path_storage); 00317 00318 if (::truncate(p.begin(), size) == -1) 00319 return std::error_code(errno, std::generic_category()); 00320 00321 return std::error_code(); 00322 } 00323 00324 static int convertAccessMode(AccessMode Mode) { 00325 switch (Mode) { 00326 case AccessMode::Exist: 00327 return F_OK; 00328 case AccessMode::Write: 00329 return W_OK; 00330 case AccessMode::Execute: 00331 return R_OK | X_OK; // scripts also need R_OK. 00332 } 00333 llvm_unreachable("invalid enum"); 00334 } 00335 00336 std::error_code access(const Twine &Path, AccessMode Mode) { 00337 SmallString<128> PathStorage; 00338 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 00339 00340 if (::access(P.begin(), convertAccessMode(Mode)) == -1) 00341 return std::error_code(errno, std::generic_category()); 00342 00343 if (Mode == AccessMode::Execute) { 00344 // Don't say that directories are executable. 00345 struct stat buf; 00346 if (0 != stat(P.begin(), &buf)) 00347 return errc::permission_denied; 00348 if (!S_ISREG(buf.st_mode)) 00349 return errc::permission_denied; 00350 } 00351 00352 return std::error_code(); 00353 } 00354 00355 bool equivalent(file_status A, file_status B) { 00356 assert(status_known(A) && status_known(B)); 00357 return A.fs_st_dev == B.fs_st_dev && 00358 A.fs_st_ino == B.fs_st_ino; 00359 } 00360 00361 std::error_code equivalent(const Twine &A, const Twine &B, bool &result) { 00362 file_status fsA, fsB; 00363 if (std::error_code ec = status(A, fsA)) 00364 return ec; 00365 if (std::error_code ec = status(B, fsB)) 00366 return ec; 00367 result = equivalent(fsA, fsB); 00368 return std::error_code(); 00369 } 00370 00371 static std::error_code fillStatus(int StatRet, const struct stat &Status, 00372 file_status &Result) { 00373 if (StatRet != 0) { 00374 std::error_code ec(errno, std::generic_category()); 00375 if (ec == errc::no_such_file_or_directory) 00376 Result = file_status(file_type::file_not_found); 00377 else 00378 Result = file_status(file_type::status_error); 00379 return ec; 00380 } 00381 00382 file_type Type = file_type::type_unknown; 00383 00384 if (S_ISDIR(Status.st_mode)) 00385 Type = file_type::directory_file; 00386 else if (S_ISREG(Status.st_mode)) 00387 Type = file_type::regular_file; 00388 else if (S_ISBLK(Status.st_mode)) 00389 Type = file_type::block_file; 00390 else if (S_ISCHR(Status.st_mode)) 00391 Type = file_type::character_file; 00392 else if (S_ISFIFO(Status.st_mode)) 00393 Type = file_type::fifo_file; 00394 else if (S_ISSOCK(Status.st_mode)) 00395 Type = file_type::socket_file; 00396 00397 perms Perms = static_cast<perms>(Status.st_mode); 00398 Result = 00399 file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_mtime, 00400 Status.st_uid, Status.st_gid, Status.st_size); 00401 00402 return std::error_code(); 00403 } 00404 00405 std::error_code status(const Twine &Path, file_status &Result) { 00406 SmallString<128> PathStorage; 00407 StringRef P = Path.toNullTerminatedStringRef(PathStorage); 00408 00409 struct stat Status; 00410 int StatRet = ::stat(P.begin(), &Status); 00411 return fillStatus(StatRet, Status, Result); 00412 } 00413 00414 std::error_code status(int FD, file_status &Result) { 00415 struct stat Status; 00416 int StatRet = ::fstat(FD, &Status); 00417 return fillStatus(StatRet, Status, Result); 00418 } 00419 00420 std::error_code setLastModificationAndAccessTime(int FD, TimeValue Time) { 00421 #if defined(HAVE_FUTIMENS) 00422 timespec Times[2]; 00423 Times[0].tv_sec = Time.toEpochTime(); 00424 Times[0].tv_nsec = 0; 00425 Times[1] = Times[0]; 00426 if (::futimens(FD, Times)) 00427 return std::error_code(errno, std::generic_category()); 00428 return std::error_code(); 00429 #elif defined(HAVE_FUTIMES) 00430 timeval Times[2]; 00431 Times[0].tv_sec = Time.toEpochTime(); 00432 Times[0].tv_usec = 0; 00433 Times[1] = Times[0]; 00434 if (::futimes(FD, Times)) 00435 return std::error_code(errno, std::generic_category()); 00436 return std::error_code(); 00437 #else 00438 #warning Missing futimes() and futimens() 00439 return make_error_code(errc::function_not_supported); 00440 #endif 00441 } 00442 00443 std::error_code mapped_file_region::init(int FD, bool CloseFD, uint64_t Offset) { 00444 AutoFD ScopedFD(FD); 00445 if (!CloseFD) 00446 ScopedFD.take(); 00447 00448 // Figure out how large the file is. 00449 struct stat FileInfo; 00450 if (fstat(FD, &FileInfo) == -1) 00451 return std::error_code(errno, std::generic_category()); 00452 uint64_t FileSize = FileInfo.st_size; 00453 00454 if (Size == 0) 00455 Size = FileSize; 00456 else if (FileSize < Size) { 00457 // We need to grow the file. 00458 if (ftruncate(FD, Size) == -1) 00459 return std::error_code(errno, std::generic_category()); 00460 } 00461 00462 int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE; 00463 int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE); 00464 #ifdef MAP_FILE 00465 flags |= MAP_FILE; 00466 #endif 00467 Mapping = ::mmap(nullptr, Size, prot, flags, FD, Offset); 00468 if (Mapping == MAP_FAILED) 00469 return std::error_code(errno, std::generic_category()); 00470 return std::error_code(); 00471 } 00472 00473 mapped_file_region::mapped_file_region(const Twine &path, 00474 mapmode mode, 00475 uint64_t length, 00476 uint64_t offset, 00477 std::error_code &ec) 00478 : Mode(mode) 00479 , Size(length) 00480 , Mapping() { 00481 // Make sure that the requested size fits within SIZE_T. 00482 if (length > std::numeric_limits<size_t>::max()) { 00483 ec = make_error_code(errc::invalid_argument); 00484 return; 00485 } 00486 00487 SmallString<128> path_storage; 00488 StringRef name = path.toNullTerminatedStringRef(path_storage); 00489 int oflags = (mode == readonly) ? O_RDONLY : O_RDWR; 00490 int ofd = ::open(name.begin(), oflags); 00491 if (ofd == -1) { 00492 ec = std::error_code(errno, std::generic_category()); 00493 return; 00494 } 00495 00496 ec = init(ofd, true, offset); 00497 if (ec) 00498 Mapping = nullptr; 00499 } 00500 00501 mapped_file_region::mapped_file_region(int fd, 00502 bool closefd, 00503 mapmode mode, 00504 uint64_t length, 00505 uint64_t offset, 00506 std::error_code &ec) 00507 : Mode(mode) 00508 , Size(length) 00509 , Mapping() { 00510 // Make sure that the requested size fits within SIZE_T. 00511 if (length > std::numeric_limits<size_t>::max()) { 00512 ec = make_error_code(errc::invalid_argument); 00513 return; 00514 } 00515 00516 ec = init(fd, closefd, offset); 00517 if (ec) 00518 Mapping = nullptr; 00519 } 00520 00521 mapped_file_region::~mapped_file_region() { 00522 if (Mapping) 00523 ::munmap(Mapping, Size); 00524 } 00525 00526 mapped_file_region::mapped_file_region(mapped_file_region &&other) 00527 : Mode(other.Mode), Size(other.Size), Mapping(other.Mapping) { 00528 other.Mapping = nullptr; 00529 } 00530 00531 mapped_file_region::mapmode mapped_file_region::flags() const { 00532 assert(Mapping && "Mapping failed but used anyway!"); 00533 return Mode; 00534 } 00535 00536 uint64_t mapped_file_region::size() const { 00537 assert(Mapping && "Mapping failed but used anyway!"); 00538 return Size; 00539 } 00540 00541 char *mapped_file_region::data() const { 00542 assert(Mapping && "Mapping failed but used anyway!"); 00543 assert(Mode != readonly && "Cannot get non-const data for readonly mapping!"); 00544 return reinterpret_cast<char*>(Mapping); 00545 } 00546 00547 const char *mapped_file_region::const_data() const { 00548 assert(Mapping && "Mapping failed but used anyway!"); 00549 return reinterpret_cast<const char*>(Mapping); 00550 } 00551 00552 int mapped_file_region::alignment() { 00553 return process::get_self()->page_size(); 00554 } 00555 00556 std::error_code detail::directory_iterator_construct(detail::DirIterState &it, 00557 StringRef path){ 00558 SmallString<128> path_null(path); 00559 DIR *directory = ::opendir(path_null.c_str()); 00560 if (!directory) 00561 return std::error_code(errno, std::generic_category()); 00562 00563 it.IterationHandle = reinterpret_cast<intptr_t>(directory); 00564 // Add something for replace_filename to replace. 00565 path::append(path_null, "."); 00566 it.CurrentEntry = directory_entry(path_null.str()); 00567 return directory_iterator_increment(it); 00568 } 00569 00570 std::error_code detail::directory_iterator_destruct(detail::DirIterState &it) { 00571 if (it.IterationHandle) 00572 ::closedir(reinterpret_cast<DIR *>(it.IterationHandle)); 00573 it.IterationHandle = 0; 00574 it.CurrentEntry = directory_entry(); 00575 return std::error_code(); 00576 } 00577 00578 std::error_code detail::directory_iterator_increment(detail::DirIterState &it) { 00579 errno = 0; 00580 dirent *cur_dir = ::readdir(reinterpret_cast<DIR *>(it.IterationHandle)); 00581 if (cur_dir == nullptr && errno != 0) { 00582 return std::error_code(errno, std::generic_category()); 00583 } else if (cur_dir != nullptr) { 00584 StringRef name(cur_dir->d_name, NAMLEN(cur_dir)); 00585 if ((name.size() == 1 && name[0] == '.') || 00586 (name.size() == 2 && name[0] == '.' && name[1] == '.')) 00587 return directory_iterator_increment(it); 00588 it.CurrentEntry.replace_filename(name); 00589 } else 00590 return directory_iterator_destruct(it); 00591 00592 return std::error_code(); 00593 } 00594 00595 std::error_code openFileForRead(const Twine &Name, int &ResultFD) { 00596 SmallString<128> Storage; 00597 StringRef P = Name.toNullTerminatedStringRef(Storage); 00598 while ((ResultFD = open(P.begin(), O_RDONLY)) < 0) { 00599 if (errno != EINTR) 00600 return std::error_code(errno, std::generic_category()); 00601 } 00602 return std::error_code(); 00603 } 00604 00605 std::error_code openFileForWrite(const Twine &Name, int &ResultFD, 00606 sys::fs::OpenFlags Flags, unsigned Mode) { 00607 // Verify that we don't have both "append" and "excl". 00608 assert((!(Flags & sys::fs::F_Excl) || !(Flags & sys::fs::F_Append)) && 00609 "Cannot specify both 'excl' and 'append' file creation flags!"); 00610 00611 int OpenFlags = O_CREAT; 00612 00613 if (Flags & F_RW) 00614 OpenFlags |= O_RDWR; 00615 else 00616 OpenFlags |= O_WRONLY; 00617 00618 if (Flags & F_Append) 00619 OpenFlags |= O_APPEND; 00620 else 00621 OpenFlags |= O_TRUNC; 00622 00623 if (Flags & F_Excl) 00624 OpenFlags |= O_EXCL; 00625 00626 SmallString<128> Storage; 00627 StringRef P = Name.toNullTerminatedStringRef(Storage); 00628 while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) { 00629 if (errno != EINTR) 00630 return std::error_code(errno, std::generic_category()); 00631 } 00632 return std::error_code(); 00633 } 00634 00635 } // end namespace fs 00636 00637 namespace path { 00638 00639 bool home_directory(SmallVectorImpl<char> &result) { 00640 if (char *RequestedDir = getenv("HOME")) { 00641 result.clear(); 00642 result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 00643 return true; 00644 } 00645 00646 return false; 00647 } 00648 00649 static const char *getEnvTempDir() { 00650 // Check whether the temporary directory is specified by an environment 00651 // variable. 00652 const char *EnvironmentVariables[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"}; 00653 for (const char *Env : EnvironmentVariables) { 00654 if (const char *Dir = std::getenv(Env)) 00655 return Dir; 00656 } 00657 00658 return nullptr; 00659 } 00660 00661 static const char *getDefaultTempDir(bool ErasedOnReboot) { 00662 #ifdef P_tmpdir 00663 if ((bool)P_tmpdir) 00664 return P_tmpdir; 00665 #endif 00666 00667 if (ErasedOnReboot) 00668 return "/tmp"; 00669 return "/var/tmp"; 00670 } 00671 00672 void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) { 00673 Result.clear(); 00674 00675 if (ErasedOnReboot) { 00676 // There is no env variable for the cache directory. 00677 if (const char *RequestedDir = getEnvTempDir()) { 00678 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 00679 return; 00680 } 00681 } 00682 00683 #if defined(_CS_DARWIN_USER_TEMP_DIR) && defined(_CS_DARWIN_USER_CACHE_DIR) 00684 // On Darwin, use DARWIN_USER_TEMP_DIR or DARWIN_USER_CACHE_DIR. 00685 // macros defined in <unistd.h> on darwin >= 9 00686 int ConfName = ErasedOnReboot? _CS_DARWIN_USER_TEMP_DIR 00687 : _CS_DARWIN_USER_CACHE_DIR; 00688 size_t ConfLen = confstr(ConfName, nullptr, 0); 00689 if (ConfLen > 0) { 00690 do { 00691 Result.resize(ConfLen); 00692 ConfLen = confstr(ConfName, Result.data(), Result.size()); 00693 } while (ConfLen > 0 && ConfLen != Result.size()); 00694 00695 if (ConfLen > 0) { 00696 assert(Result.back() == 0); 00697 Result.pop_back(); 00698 return; 00699 } 00700 00701 Result.clear(); 00702 } 00703 #endif 00704 00705 const char *RequestedDir = getDefaultTempDir(ErasedOnReboot); 00706 Result.append(RequestedDir, RequestedDir + strlen(RequestedDir)); 00707 } 00708 00709 } // end namespace path 00710 00711 } // end namespace sys 00712 } // end namespace llvm