LLVM API Documentation

Unix/Path.inc
Go to the documentation of this file.
00001 //===- llvm/Support/Unix/Path.cpp - 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 portion of the Path class.
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 #if HAVE_SYS_STAT_H
00021 #include <sys/stat.h>
00022 #endif
00023 #if HAVE_FCNTL_H
00024 #include <fcntl.h>
00025 #endif
00026 #ifdef HAVE_SYS_MMAN_H
00027 #include <sys/mman.h>
00028 #endif
00029 #ifdef HAVE_SYS_STAT_H
00030 #include <sys/stat.h>
00031 #endif
00032 #if HAVE_UTIME_H
00033 #include <utime.h>
00034 #endif
00035 #if HAVE_TIME_H
00036 #include <time.h>
00037 #endif
00038 #if HAVE_DIRENT_H
00039 # include <dirent.h>
00040 # define NAMLEN(dirent) strlen((dirent)->d_name)
00041 #else
00042 # define dirent direct
00043 # define NAMLEN(dirent) (dirent)->d_namlen
00044 # if HAVE_SYS_NDIR_H
00045 #  include <sys/ndir.h>
00046 # endif
00047 # if HAVE_SYS_DIR_H
00048 #  include <sys/dir.h>
00049 # endif
00050 # if HAVE_NDIR_H
00051 #  include <ndir.h>
00052 # endif
00053 #endif
00054 
00055 #if HAVE_DLFCN_H
00056 #include <dlfcn.h>
00057 #endif
00058 
00059 #ifdef __APPLE__
00060 #include <mach-o/dyld.h>
00061 #endif
00062 
00063 // For GNU Hurd
00064 #if defined(__GNU__) && !defined(MAXPATHLEN)
00065 # define MAXPATHLEN 4096
00066 #endif
00067 
00068 // Put in a hack for Cygwin which falsely reports that the mkdtemp function
00069 // is available when it is not.
00070 #ifdef __CYGWIN__
00071 # undef HAVE_MKDTEMP
00072 #endif
00073 
00074 namespace {
00075 inline bool lastIsSlash(const std::string& path) {
00076   return !path.empty() && path[path.length() - 1] == '/';
00077 }
00078 
00079 }
00080 
00081 namespace llvm {
00082 using namespace sys;
00083 
00084 const char sys::PathSeparator = ':';
00085 
00086 StringRef Path::GetEXESuffix() {
00087   return StringRef();
00088 }
00089 
00090 Path::Path(StringRef p)
00091   : path(p) {}
00092 
00093 Path::Path(const char *StrStart, unsigned StrLen)
00094   : path(StrStart, StrLen) {}
00095 
00096 Path&
00097 Path::operator=(StringRef that) {
00098   path.assign(that.data(), that.size());
00099   return *this;
00100 }
00101 
00102 bool
00103 Path::isValid() const {
00104   // Empty paths are considered invalid here.
00105   // This code doesn't check MAXPATHLEN because there's no need. Nothing in
00106   // LLVM manipulates Paths with fixed-sizes arrays, and if the OS can't
00107   // handle names longer than some limit, it'll report this on demand using
00108   // ENAMETOLONG.
00109   return !path.empty();
00110 }
00111 
00112 bool
00113 Path::isAbsolute(const char *NameStart, unsigned NameLen) {
00114   assert(NameStart);
00115   if (NameLen == 0)
00116     return false;
00117   return NameStart[0] == '/';
00118 }
00119 
00120 bool
00121 Path::isAbsolute() const {
00122   if (path.empty())
00123     return false;
00124   return path[0] == '/';
00125 }
00126 
00127 Path
00128 Path::GetRootDirectory() {
00129   Path result;
00130   result.set("/");
00131   return result;
00132 }
00133 
00134 Path
00135 Path::GetTemporaryDirectory(std::string *ErrMsg) {
00136 #if defined(HAVE_MKDTEMP)
00137   // The best way is with mkdtemp but that's not available on many systems,
00138   // Linux and FreeBSD have it. Others probably won't.
00139   char pathname[] = "/tmp/llvm_XXXXXX";
00140   if (0 == mkdtemp(pathname)) {
00141     MakeErrMsg(ErrMsg,
00142                std::string(pathname) + ": can't create temporary directory");
00143     return Path();
00144   }
00145   return Path(pathname);
00146 #elif defined(HAVE_MKSTEMP)
00147   // If no mkdtemp is available, mkstemp can be used to create a temporary file
00148   // which is then removed and created as a directory. We prefer this over
00149   // mktemp because of mktemp's inherent security and threading risks. We still
00150   // have a slight race condition from the time the temporary file is created to
00151   // the time it is re-created as a directoy.
00152   char pathname[] = "/tmp/llvm_XXXXXX";
00153   int fd = 0;
00154   if (-1 == (fd = mkstemp(pathname))) {
00155     MakeErrMsg(ErrMsg,
00156       std::string(pathname) + ": can't create temporary directory");
00157     return Path();
00158   }
00159   ::close(fd);
00160   ::unlink(pathname); // start race condition, ignore errors
00161   if (-1 == ::mkdir(pathname, S_IRWXU)) { // end race condition
00162     MakeErrMsg(ErrMsg,
00163       std::string(pathname) + ": can't create temporary directory");
00164     return Path();
00165   }
00166   return Path(pathname);
00167 #elif defined(HAVE_MKTEMP)
00168   // If a system doesn't have mkdtemp(3) or mkstemp(3) but it does have
00169   // mktemp(3) then we'll assume that system (e.g. AIX) has a reasonable
00170   // implementation of mktemp(3) and doesn't follow BSD 4.3's lead of replacing
00171   // the XXXXXX with the pid of the process and a letter. That leads to only
00172   // twenty six temporary files that can be generated.
00173   char pathname[] = "/tmp/llvm_XXXXXX";
00174   char *TmpName = ::mktemp(pathname);
00175   if (TmpName == 0) {
00176     MakeErrMsg(ErrMsg,
00177       std::string(TmpName) + ": can't create unique directory name");
00178     return Path();
00179   }
00180   if (-1 == ::mkdir(TmpName, S_IRWXU)) {
00181     MakeErrMsg(ErrMsg,
00182         std::string(TmpName) + ": can't create temporary directory");
00183     return Path();
00184   }
00185   return Path(TmpName);
00186 #else
00187   // This is the worst case implementation. tempnam(3) leaks memory unless its
00188   // on an SVID2 (or later) system. On BSD 4.3 it leaks. tmpnam(3) has thread
00189   // issues. The mktemp(3) function doesn't have enough variability in the
00190   // temporary name generated. So, we provide our own implementation that
00191   // increments an integer from a random number seeded by the current time. This
00192   // should be sufficiently unique that we don't have many collisions between
00193   // processes. Generally LLVM processes don't run very long and don't use very
00194   // many temporary files so this shouldn't be a big issue for LLVM.
00195   static time_t num = ::time(0);
00196   char pathname[MAXPATHLEN];
00197   do {
00198     num++;
00199     sprintf(pathname, "/tmp/llvm_%010u", unsigned(num));
00200   } while ( 0 == access(pathname, F_OK ) );
00201   if (-1 == ::mkdir(pathname, S_IRWXU)) {
00202     MakeErrMsg(ErrMsg,
00203       std::string(pathname) + ": can't create temporary directory");
00204     return Path();
00205   }
00206   return Path(pathname);
00207 #endif
00208 }
00209 
00210 void
00211 Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) {
00212 #ifdef LTDL_SHLIBPATH_VAR
00213   char* env_var = getenv(LTDL_SHLIBPATH_VAR);
00214   if (env_var != 0) {
00215     getPathList(env_var,Paths);
00216   }
00217 #endif
00218   // FIXME: Should this look at LD_LIBRARY_PATH too?
00219   Paths.push_back(sys::Path("/usr/local/lib/"));
00220   Paths.push_back(sys::Path("/usr/X11R6/lib/"));
00221   Paths.push_back(sys::Path("/usr/lib/"));
00222   Paths.push_back(sys::Path("/lib/"));
00223 }
00224 
00225 void
00226 Path::GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths) {
00227   char * env_var = getenv("LLVM_LIB_SEARCH_PATH");
00228   if (env_var != 0) {
00229     getPathList(env_var,Paths);
00230   }
00231 #ifdef LLVM_LIBDIR
00232   {
00233     Path tmpPath;
00234     if (tmpPath.set(LLVM_LIBDIR))
00235       if (tmpPath.canRead())
00236         Paths.push_back(tmpPath);
00237   }
00238 #endif
00239   GetSystemLibraryPaths(Paths);
00240 }
00241 
00242 Path
00243 Path::GetUserHomeDirectory() {
00244   const char* home = getenv("HOME");
00245   Path result;
00246   if (home && result.set(home))
00247     return result;
00248   result.set("/");
00249   return result;
00250 }
00251 
00252 Path
00253 Path::GetCurrentDirectory() {
00254   char pathname[MAXPATHLEN];
00255   if (!getcwd(pathname, MAXPATHLEN)) {
00256     assert(false && "Could not query current working directory.");
00257     return Path();
00258   }
00259 
00260   return Path(pathname);
00261 }
00262 
00263 #if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
00264     defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \
00265     defined(__linux__) || defined(__CYGWIN__)
00266 static int
00267 test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
00268     const char *dir, const char *bin)
00269 {
00270   struct stat sb;
00271 
00272   snprintf(buf, PATH_MAX, "%s/%s", dir, bin);
00273   if (realpath(buf, ret) == NULL)
00274     return (1);
00275   if (stat(buf, &sb) != 0)
00276     return (1);
00277 
00278   return (0);
00279 }
00280 
00281 static char *
00282 getprogpath(char ret[PATH_MAX], const char *bin)
00283 {
00284   char *pv, *s, *t, buf[PATH_MAX];
00285 
00286   /* First approach: absolute path. */
00287   if (bin[0] == '/') {
00288     if (test_dir(buf, ret, "/", bin) == 0)
00289       return (ret);
00290     return (NULL);
00291   }
00292 
00293   /* Second approach: relative path. */
00294   if (strchr(bin, '/') != NULL) {
00295     if (getcwd(buf, PATH_MAX) == NULL)
00296       return (NULL);
00297     if (test_dir(buf, ret, buf, bin) == 0)
00298       return (ret);
00299     return (NULL);
00300   }
00301 
00302   /* Third approach: $PATH */
00303   if ((pv = getenv("PATH")) == NULL)
00304     return (NULL);
00305   s = pv = strdup(pv);
00306   if (pv == NULL)
00307     return (NULL);
00308   while ((t = strsep(&s, ":")) != NULL) {
00309     if (test_dir(buf, ret, t, bin) == 0) {
00310       free(pv);
00311       return (ret);
00312     }
00313   }
00314   free(pv);
00315   return (NULL);
00316 }
00317 #endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__
00318 
00319 /// GetMainExecutable - Return the path to the main executable, given the
00320 /// value of argv[0] from program startup.
00321 Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
00322 #if defined(__APPLE__)
00323   // On OS X the executable path is saved to the stack by dyld. Reading it
00324   // from there is much faster than calling dladdr, especially for large
00325   // binaries with symbols.
00326   char exe_path[MAXPATHLEN];
00327   uint32_t size = sizeof(exe_path);
00328   if (_NSGetExecutablePath(exe_path, &size) == 0) {
00329     char link_path[MAXPATHLEN];
00330     if (realpath(exe_path, link_path))
00331       return Path(link_path);
00332   }
00333 #elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
00334       defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__)
00335   char exe_path[PATH_MAX];
00336 
00337   if (getprogpath(exe_path, argv0) != NULL)
00338     return Path(exe_path);
00339 #elif defined(__linux__) || defined(__CYGWIN__)
00340   char exe_path[MAXPATHLEN];
00341   StringRef aPath("/proc/self/exe");
00342   if (sys::fs::exists(aPath)) {
00343       // /proc is not always mounted under Linux (chroot for example).
00344       ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path));
00345       if (len >= 0)
00346           return Path(StringRef(exe_path, len));
00347   } else {
00348       // Fall back to the classical detection.
00349       if (getprogpath(exe_path, argv0) != NULL)
00350           return Path(exe_path);
00351   }
00352 #elif defined(HAVE_DLFCN_H)
00353   // Use dladdr to get executable path if available.
00354   Dl_info DLInfo;
00355   int err = dladdr(MainAddr, &DLInfo);
00356   if (err == 0)
00357     return Path();
00358 
00359   // If the filename is a symlink, we need to resolve and return the location of
00360   // the actual executable.
00361   char link_path[MAXPATHLEN];
00362   if (realpath(DLInfo.dli_fname, link_path))
00363     return Path(link_path);
00364 #else
00365 #error GetMainExecutable is not implemented on this host yet.
00366 #endif
00367   return Path();
00368 }
00369 
00370 
00371 StringRef Path::getDirname() const {
00372   return getDirnameCharSep(path, "/");
00373 }
00374 
00375 StringRef
00376 Path::getBasename() const {
00377   // Find the last slash
00378   std::string::size_type slash = path.rfind('/');
00379   if (slash == std::string::npos)
00380     slash = 0;
00381   else
00382     slash++;
00383 
00384   std::string::size_type dot = path.rfind('.');
00385   if (dot == std::string::npos || dot < slash)
00386     return StringRef(path).substr(slash);
00387   else
00388     return StringRef(path).substr(slash, dot - slash);
00389 }
00390 
00391 StringRef
00392 Path::getSuffix() const {
00393   // Find the last slash
00394   std::string::size_type slash = path.rfind('/');
00395   if (slash == std::string::npos)
00396     slash = 0;
00397   else
00398     slash++;
00399 
00400   std::string::size_type dot = path.rfind('.');
00401   if (dot == std::string::npos || dot < slash)
00402     return StringRef();
00403   else
00404     return StringRef(path).substr(dot + 1);
00405 }
00406 
00407 bool Path::getMagicNumber(std::string &Magic, unsigned len) const {
00408   assert(len < 1024 && "Request for magic string too long");
00409   char Buf[1025];
00410   int fd = ::open(path.c_str(), O_RDONLY);
00411   if (fd < 0)
00412     return false;
00413   ssize_t bytes_read = ::read(fd, Buf, len);
00414   ::close(fd);
00415   if (ssize_t(len) != bytes_read)
00416     return false;
00417   Magic.assign(Buf, len);
00418   return true;
00419 }
00420 
00421 bool
00422 Path::exists() const {
00423   return 0 == access(path.c_str(), F_OK );
00424 }
00425 
00426 bool
00427 Path::isDirectory() const {
00428   struct stat buf;
00429   if (0 != stat(path.c_str(), &buf))
00430     return false;
00431   return ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false;
00432 }
00433 
00434 bool
00435 Path::isSymLink() const {
00436   struct stat buf;
00437   if (0 != lstat(path.c_str(), &buf))
00438     return false;
00439   return S_ISLNK(buf.st_mode);
00440 }
00441 
00442 
00443 bool
00444 Path::canRead() const {
00445   return 0 == access(path.c_str(), R_OK);
00446 }
00447 
00448 bool
00449 Path::canWrite() const {
00450   return 0 == access(path.c_str(), W_OK);
00451 }
00452 
00453 bool
00454 Path::isRegularFile() const {
00455   // Get the status so we can determine if it's a file or directory
00456   struct stat buf;
00457 
00458   if (0 != stat(path.c_str(), &buf))
00459     return false;
00460 
00461   if (S_ISREG(buf.st_mode))
00462     return true;
00463 
00464   return false;
00465 }
00466 
00467 bool
00468 Path::canExecute() const {
00469   if (0 != access(path.c_str(), R_OK | X_OK ))
00470     return false;
00471   struct stat buf;
00472   if (0 != stat(path.c_str(), &buf))
00473     return false;
00474   if (!S_ISREG(buf.st_mode))
00475     return false;
00476   return true;
00477 }
00478 
00479 StringRef
00480 Path::getLast() const {
00481   // Find the last slash
00482   size_t pos = path.rfind('/');
00483 
00484   // Handle the corner cases
00485   if (pos == std::string::npos)
00486     return path;
00487 
00488   // If the last character is a slash
00489   if (pos == path.length()-1) {
00490     // Find the second to last slash
00491     size_t pos2 = path.rfind('/', pos-1);
00492     if (pos2 == std::string::npos)
00493       return StringRef(path).substr(0,pos);
00494     else
00495       return StringRef(path).substr(pos2+1,pos-pos2-1);
00496   }
00497   // Return everything after the last slash
00498   return StringRef(path).substr(pos+1);
00499 }
00500 
00501 const FileStatus *
00502 PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const {
00503   if (!fsIsValid || update) {
00504     struct stat buf;
00505     if (0 != stat(path.c_str(), &buf)) {
00506       MakeErrMsg(ErrStr, path + ": can't get status of file");
00507       return 0;
00508     }
00509     status.fileSize = buf.st_size;
00510     status.modTime.fromEpochTime(buf.st_mtime);
00511     status.mode = buf.st_mode;
00512     status.user = buf.st_uid;
00513     status.group = buf.st_gid;
00514     status.uniqueID = uint64_t(buf.st_ino);
00515     status.isDir  = S_ISDIR(buf.st_mode);
00516     status.isFile = S_ISREG(buf.st_mode);
00517     fsIsValid = true;
00518   }
00519   return &status;
00520 }
00521 
00522 static bool AddPermissionBits(const Path &File, int bits) {
00523   // Get the umask value from the operating system.  We want to use it
00524   // when changing the file's permissions. Since calling umask() sets
00525   // the umask and returns its old value, we must call it a second
00526   // time to reset it to the user's preference.
00527   int mask = umask(0777); // The arg. to umask is arbitrary.
00528   umask(mask);            // Restore the umask.
00529 
00530   // Get the file's current mode.
00531   struct stat buf;
00532   if (0 != stat(File.c_str(), &buf))
00533     return false;
00534   // Change the file to have whichever permissions bits from 'bits'
00535   // that the umask would not disable.
00536   if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1)
00537       return false;
00538   return true;
00539 }
00540 
00541 bool Path::makeReadableOnDisk(std::string* ErrMsg) {
00542   if (!AddPermissionBits(*this, 0444))
00543     return MakeErrMsg(ErrMsg, path + ": can't make file readable");
00544   return false;
00545 }
00546 
00547 bool Path::makeWriteableOnDisk(std::string* ErrMsg) {
00548   if (!AddPermissionBits(*this, 0222))
00549     return MakeErrMsg(ErrMsg, path + ": can't make file writable");
00550   return false;
00551 }
00552 
00553 bool Path::makeExecutableOnDisk(std::string* ErrMsg) {
00554   if (!AddPermissionBits(*this, 0111))
00555     return MakeErrMsg(ErrMsg, path + ": can't make file executable");
00556   return false;
00557 }
00558 
00559 bool
00560 Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const {
00561   DIR* direntries = ::opendir(path.c_str());
00562   if (direntries == 0)
00563     return MakeErrMsg(ErrMsg, path + ": can't open directory");
00564 
00565   std::string dirPath = path;
00566   if (!lastIsSlash(dirPath))
00567     dirPath += '/';
00568 
00569   result.clear();
00570   struct dirent* de = ::readdir(direntries);
00571   for ( ; de != 0; de = ::readdir(direntries)) {
00572     if (de->d_name[0] != '.') {
00573       Path aPath(dirPath + (const char*)de->d_name);
00574       struct stat st;
00575       if (0 != lstat(aPath.path.c_str(), &st)) {
00576         if (S_ISLNK(st.st_mode))
00577           continue; // dangling symlink -- ignore
00578         return MakeErrMsg(ErrMsg,
00579                           aPath.path +  ": can't determine file object type");
00580       }
00581       result.insert(aPath);
00582     }
00583   }
00584 
00585   closedir(direntries);
00586   return false;
00587 }
00588 
00589 bool
00590 Path::set(StringRef a_path) {
00591   if (a_path.empty())
00592     return false;
00593   path = a_path;
00594   return true;
00595 }
00596 
00597 bool
00598 Path::appendComponent(StringRef name) {
00599   if (name.empty())
00600     return false;
00601   if (!lastIsSlash(path))
00602     path += '/';
00603   path += name;
00604   return true;
00605 }
00606 
00607 bool
00608 Path::eraseComponent() {
00609   size_t slashpos = path.rfind('/',path.size());
00610   if (slashpos == 0 || slashpos == std::string::npos) {
00611     path.erase();
00612     return true;
00613   }
00614   if (slashpos == path.size() - 1)
00615     slashpos = path.rfind('/',slashpos-1);
00616   if (slashpos == std::string::npos) {
00617     path.erase();
00618     return true;
00619   }
00620   path.erase(slashpos);
00621   return true;
00622 }
00623 
00624 bool
00625 Path::eraseSuffix() {
00626   size_t dotpos = path.rfind('.',path.size());
00627   size_t slashpos = path.rfind('/',path.size());
00628   if (dotpos != std::string::npos) {
00629     if (slashpos == std::string::npos || dotpos > slashpos+1) {
00630       path.erase(dotpos, path.size()-dotpos);
00631       return true;
00632     }
00633   }
00634   return false;
00635 }
00636 
00637 static bool createDirectoryHelper(char* beg, char* end, bool create_parents) {
00638 
00639   if (access(beg, R_OK | W_OK) == 0)
00640     return false;
00641 
00642   if (create_parents) {
00643 
00644     char* c = end;
00645 
00646     for (; c != beg; --c)
00647       if (*c == '/') {
00648 
00649         // Recurse to handling the parent directory.
00650         *c = '\0';
00651         bool x = createDirectoryHelper(beg, c, create_parents);
00652         *c = '/';
00653 
00654         // Return if we encountered an error.
00655         if (x)
00656           return true;
00657 
00658         break;
00659       }
00660   }
00661 
00662   return mkdir(beg, S_IRWXU | S_IRWXG) != 0;
00663 }
00664 
00665 bool
00666 Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) {
00667   // Get a writeable copy of the path name
00668   std::string pathname(path);
00669 
00670   // Null-terminate the last component
00671   size_t lastchar = path.length() - 1 ;
00672 
00673   if (pathname[lastchar] != '/')
00674     ++lastchar;
00675 
00676   pathname[lastchar] = '\0';
00677 
00678   if (createDirectoryHelper(&pathname[0], &pathname[lastchar], create_parents))
00679     return MakeErrMsg(ErrMsg, pathname + ": can't create directory");
00680 
00681   return false;
00682 }
00683 
00684 bool
00685 Path::createFileOnDisk(std::string* ErrMsg) {
00686   // Create the file
00687   int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR);
00688   if (fd < 0)
00689     return MakeErrMsg(ErrMsg, path + ": can't create file");
00690   ::close(fd);
00691   return false;
00692 }
00693 
00694 bool
00695 Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) {
00696   // Make this into a unique file name
00697   if (makeUnique( reuse_current, ErrMsg ))
00698     return true;
00699 
00700   // create the file
00701   int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
00702   if (fd < 0)
00703     return MakeErrMsg(ErrMsg, path + ": can't create temporary file");
00704   ::close(fd);
00705   return false;
00706 }
00707 
00708 bool
00709 Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
00710   // Get the status so we can determine if it's a file or directory.
00711   struct stat buf;
00712   if (0 != stat(path.c_str(), &buf)) {
00713     MakeErrMsg(ErrStr, path + ": can't get status of file");
00714     return true;
00715   }
00716 
00717   // Note: this check catches strange situations. In all cases, LLVM should
00718   // only be involved in the creation and deletion of regular files.  This
00719   // check ensures that what we're trying to erase is a regular file. It
00720   // effectively prevents LLVM from erasing things like /dev/null, any block
00721   // special file, or other things that aren't "regular" files.
00722   if (S_ISREG(buf.st_mode)) {
00723     if (unlink(path.c_str()) != 0)
00724       return MakeErrMsg(ErrStr, path + ": can't destroy file");
00725     return false;
00726   }
00727 
00728   if (!S_ISDIR(buf.st_mode)) {
00729     if (ErrStr) *ErrStr = "not a file or directory";
00730     return true;
00731   }
00732 
00733   if (remove_contents) {
00734     // Recursively descend the directory to remove its contents.
00735     std::string cmd = "/bin/rm -rf " + path;
00736     if (system(cmd.c_str()) != 0) {
00737       MakeErrMsg(ErrStr, path + ": failed to recursively remove directory.");
00738       return true;
00739     }
00740     return false;
00741   }
00742 
00743   // Otherwise, try to just remove the one directory.
00744   std::string pathname(path);
00745   size_t lastchar = path.length() - 1;
00746   if (pathname[lastchar] == '/')
00747     pathname[lastchar] = '\0';
00748   else
00749     pathname[lastchar+1] = '\0';
00750 
00751   if (rmdir(pathname.c_str()) != 0)
00752     return MakeErrMsg(ErrStr, pathname + ": can't erase directory");
00753   return false;
00754 }
00755 
00756 bool
00757 Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) {
00758   if (0 != ::rename(path.c_str(), newName.c_str()))
00759     return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" +
00760                newName.str() + "'");
00761   return false;
00762 }
00763 
00764 bool
00765 Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const {
00766   struct utimbuf utb;
00767   utb.actime = si.modTime.toPosixTime();
00768   utb.modtime = utb.actime;
00769   if (0 != ::utime(path.c_str(),&utb))
00770     return MakeErrMsg(ErrStr, path + ": can't set file modification time");
00771   if (0 != ::chmod(path.c_str(),si.mode))
00772     return MakeErrMsg(ErrStr, path + ": can't set mode");
00773   return false;
00774 }
00775 
00776 bool
00777 sys::CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg){
00778   int inFile = -1;
00779   int outFile = -1;
00780   inFile = ::open(Src.c_str(), O_RDONLY);
00781   if (inFile == -1)
00782     return MakeErrMsg(ErrMsg, Src.str() +
00783       ": can't open source file to copy");
00784 
00785   outFile = ::open(Dest.c_str(), O_WRONLY|O_CREAT, 0666);
00786   if (outFile == -1) {
00787     ::close(inFile);
00788     return MakeErrMsg(ErrMsg, Dest.str() +
00789       ": can't create destination file for copy");
00790   }
00791 
00792   char Buffer[16*1024];
00793   while (ssize_t Amt = ::read(inFile, Buffer, 16*1024)) {
00794     if (Amt == -1) {
00795       if (errno != EINTR && errno != EAGAIN) {
00796         ::close(inFile);
00797         ::close(outFile);
00798         return MakeErrMsg(ErrMsg, Src.str()+": can't read source file");
00799       }
00800     } else {
00801       char *BufPtr = Buffer;
00802       while (Amt) {
00803         ssize_t AmtWritten = ::write(outFile, BufPtr, Amt);
00804         if (AmtWritten == -1) {
00805           if (errno != EINTR && errno != EAGAIN) {
00806             ::close(inFile);
00807             ::close(outFile);
00808             return MakeErrMsg(ErrMsg, Dest.str() +
00809               ": can't write destination file");
00810           }
00811         } else {
00812           Amt -= AmtWritten;
00813           BufPtr += AmtWritten;
00814         }
00815       }
00816     }
00817   }
00818   ::close(inFile);
00819   ::close(outFile);
00820   return false;
00821 }
00822 
00823 bool
00824 Path::makeUnique(bool reuse_current, std::string* ErrMsg) {
00825   bool Exists;
00826   if (reuse_current && (fs::exists(path, Exists) || !Exists))
00827     return false; // File doesn't exist already, just use it!
00828 
00829   // Append an XXXXXX pattern to the end of the file for use with mkstemp,
00830   // mktemp or our own implementation.
00831   // This uses std::vector instead of SmallVector to avoid a dependence on
00832   // libSupport. And performance isn't critical here.
00833   std::vector<char> Buf;
00834   Buf.resize(path.size()+8);
00835   char *FNBuffer = &Buf[0];
00836     path.copy(FNBuffer,path.size());
00837   bool isdir;
00838   if (!fs::is_directory(path, isdir) && isdir)
00839     strcpy(FNBuffer+path.size(), "/XXXXXX");
00840   else
00841     strcpy(FNBuffer+path.size(), "-XXXXXX");
00842 
00843 #if defined(HAVE_MKSTEMP)
00844   int TempFD;
00845   if ((TempFD = mkstemp(FNBuffer)) == -1)
00846     return MakeErrMsg(ErrMsg, path + ": can't make unique filename");
00847 
00848   // We don't need to hold the temp file descriptor... we will trust that no one
00849   // will overwrite/delete the file before we can open it again.
00850   close(TempFD);
00851 
00852   // Save the name
00853   path = FNBuffer;
00854 
00855   // By default mkstemp sets the mode to 0600, so update mode bits now.
00856   AddPermissionBits (*this, 0666);
00857 #elif defined(HAVE_MKTEMP)
00858   // If we don't have mkstemp, use the old and obsolete mktemp function.
00859   if (mktemp(FNBuffer) == 0)
00860     return MakeErrMsg(ErrMsg, path + ": can't make unique filename");
00861 
00862   // Save the name
00863   path = FNBuffer;
00864 #else
00865   // Okay, looks like we have to do it all by our lonesome.
00866   static unsigned FCounter = 0;
00867   // Try to initialize with unique value.
00868   if (FCounter == 0) FCounter = ((unsigned)getpid() & 0xFFFF) << 8;
00869   char* pos = strstr(FNBuffer, "XXXXXX");
00870   do {
00871     if (++FCounter > 0xFFFFFF) {
00872       return MakeErrMsg(ErrMsg,
00873         path + ": can't make unique filename: too many files");
00874     }
00875     sprintf(pos, "%06X", FCounter);
00876     path = FNBuffer;
00877   } while (exists());
00878   // POSSIBLE SECURITY BUG: An attacker can easily guess the name and exploit
00879   // LLVM.
00880 #endif
00881   return false;
00882 }
00883 
00884 const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) {
00885   int Flags = MAP_PRIVATE;
00886 #ifdef MAP_FILE
00887   Flags |= MAP_FILE;
00888 #endif
00889   void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, Offset);
00890   if (BasePtr == MAP_FAILED)
00891     return 0;
00892   return (const char*)BasePtr;
00893 }
00894 
00895 void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) {
00896   const void *Addr = static_cast<const void *>(BasePtr);
00897   ::munmap(const_cast<void *>(Addr), FileSize);
00898 }
00899 
00900 } // end llvm namespace