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