LLVM API Documentation
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