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