1//===- llvm/Support/Unix/Path.cpp - 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 portion of the Path class. 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#if HAVE_SYS_STAT_H 21#include <sys/stat.h> 22#endif 23#if HAVE_FCNTL_H 24#include <fcntl.h> 25#endif 26#ifdef HAVE_SYS_MMAN_H 27#include <sys/mman.h> 28#endif 29#ifdef HAVE_SYS_STAT_H 30#include <sys/stat.h> 31#endif 32#if HAVE_UTIME_H 33#include <utime.h> 34#endif 35#if HAVE_TIME_H 36#include <time.h> 37#endif 38#if HAVE_DIRENT_H 39# include <dirent.h> 40# define NAMLEN(dirent) strlen((dirent)->d_name) 41#else 42# define dirent direct 43# define NAMLEN(dirent) (dirent)->d_namlen 44# if HAVE_SYS_NDIR_H 45# include <sys/ndir.h> 46# endif 47# if HAVE_SYS_DIR_H 48# include <sys/dir.h> 49# endif 50# if HAVE_NDIR_H 51# include <ndir.h> 52# endif 53#endif 54 55#if HAVE_DLFCN_H 56#include <dlfcn.h> 57#endif 58 59#ifdef __APPLE__ 60#include <mach-o/dyld.h> 61#endif 62 63// For GNU Hurd 64#if defined(__GNU__) && !defined(MAXPATHLEN) 65# define MAXPATHLEN 4096 66#endif 67 68// Put in a hack for Cygwin which falsely reports that the mkdtemp function 69// is available when it is not. 70#ifdef __CYGWIN__ 71# undef HAVE_MKDTEMP 72#endif 73 74namespace { 75inline bool lastIsSlash(const std::string& path) { 76 return !path.empty() && path[path.length() - 1] == '/'; 77} 78 79} 80 81namespace llvm { 82using namespace sys; 83 84const char sys::PathSeparator = ':'; 85 86StringRef Path::GetEXESuffix() { 87 return StringRef(); 88} 89 90Path::Path(StringRef p) 91 : path(p) {} 92 93Path::Path(const char *StrStart, unsigned StrLen) 94 : path(StrStart, StrLen) {} 95 96Path& 97Path::operator=(StringRef that) { 98 path.assign(that.data(), that.size()); 99 return *this; 100} 101 102bool 103Path::isValid() const { 104 // Empty paths are considered invalid here. 105 // This code doesn't check MAXPATHLEN because there's no need. Nothing in 106 // LLVM manipulates Paths with fixed-sizes arrays, and if the OS can't 107 // handle names longer than some limit, it'll report this on demand using 108 // ENAMETOLONG. 109 return !path.empty(); 110} 111 112bool 113Path::isAbsolute(const char *NameStart, unsigned NameLen) { 114 assert(NameStart); 115 if (NameLen == 0) 116 return false; 117 return NameStart[0] == '/'; 118} 119 120bool 121Path::isAbsolute() const { 122 if (path.empty()) 123 return false; 124 return path[0] == '/'; 125} 126 127Path 128Path::GetRootDirectory() { 129 Path result; 130 result.set("/"); 131 return result; 132} 133 134Path 135Path::GetTemporaryDirectory(std::string *ErrMsg) { 136#if defined(HAVE_MKDTEMP) 137 // The best way is with mkdtemp but that's not available on many systems, 138 // Linux and FreeBSD have it. Others probably won't. 139 char pathname[] = "/tmp/llvm_XXXXXX"; 140 if (0 == mkdtemp(pathname)) { 141 MakeErrMsg(ErrMsg, 142 std::string(pathname) + ": can't create temporary directory"); 143 return Path(); 144 } 145 return Path(pathname); 146#elif defined(HAVE_MKSTEMP) 147 // If no mkdtemp is available, mkstemp can be used to create a temporary file 148 // which is then removed and created as a directory. We prefer this over 149 // mktemp because of mktemp's inherent security and threading risks. We still 150 // have a slight race condition from the time the temporary file is created to 151 // the time it is re-created as a directoy. 152 char pathname[] = "/tmp/llvm_XXXXXX"; 153 int fd = 0; 154 if (-1 == (fd = mkstemp(pathname))) { 155 MakeErrMsg(ErrMsg, 156 std::string(pathname) + ": can't create temporary directory"); 157 return Path(); 158 } 159 ::close(fd); 160 ::unlink(pathname); // start race condition, ignore errors 161 if (-1 == ::mkdir(pathname, S_IRWXU)) { // end race condition 162 MakeErrMsg(ErrMsg, 163 std::string(pathname) + ": can't create temporary directory"); 164 return Path(); 165 } 166 return Path(pathname); 167#elif defined(HAVE_MKTEMP) 168 // If a system doesn't have mkdtemp(3) or mkstemp(3) but it does have 169 // mktemp(3) then we'll assume that system (e.g. AIX) has a reasonable 170 // implementation of mktemp(3) and doesn't follow BSD 4.3's lead of replacing 171 // the XXXXXX with the pid of the process and a letter. That leads to only 172 // twenty six temporary files that can be generated. 173 char pathname[] = "/tmp/llvm_XXXXXX"; 174 char *TmpName = ::mktemp(pathname); 175 if (TmpName == 0) { 176 MakeErrMsg(ErrMsg, 177 std::string(TmpName) + ": can't create unique directory name"); 178 return Path(); 179 } 180 if (-1 == ::mkdir(TmpName, S_IRWXU)) { 181 MakeErrMsg(ErrMsg, 182 std::string(TmpName) + ": can't create temporary directory"); 183 return Path(); 184 } 185 return Path(TmpName); 186#else 187 // This is the worst case implementation. tempnam(3) leaks memory unless its 188 // on an SVID2 (or later) system. On BSD 4.3 it leaks. tmpnam(3) has thread 189 // issues. The mktemp(3) function doesn't have enough variability in the 190 // temporary name generated. So, we provide our own implementation that 191 // increments an integer from a random number seeded by the current time. This 192 // should be sufficiently unique that we don't have many collisions between 193 // processes. Generally LLVM processes don't run very long and don't use very 194 // many temporary files so this shouldn't be a big issue for LLVM. 195 static time_t num = ::time(0); 196 char pathname[MAXPATHLEN]; 197 do { 198 num++; 199 sprintf(pathname, "/tmp/llvm_%010u", unsigned(num)); 200 } while ( 0 == access(pathname, F_OK ) ); 201 if (-1 == ::mkdir(pathname, S_IRWXU)) { 202 MakeErrMsg(ErrMsg, 203 std::string(pathname) + ": can't create temporary directory"); 204 return Path(); 205 } 206 return Path(pathname); 207#endif 208} 209 210void 211Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) { 212#ifdef LTDL_SHLIBPATH_VAR 213 char* env_var = getenv(LTDL_SHLIBPATH_VAR); 214 if (env_var != 0) { 215 getPathList(env_var,Paths); 216 } 217#endif 218 // FIXME: Should this look at LD_LIBRARY_PATH too? 219 Paths.push_back(sys::Path("/usr/local/lib/")); 220 Paths.push_back(sys::Path("/usr/X11R6/lib/")); 221 Paths.push_back(sys::Path("/usr/lib/")); 222 Paths.push_back(sys::Path("/lib/")); 223} 224 225void 226Path::GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths) { 227 char * env_var = getenv("LLVM_LIB_SEARCH_PATH"); 228 if (env_var != 0) { 229 getPathList(env_var,Paths); 230 } 231#ifdef LLVM_LIBDIR 232 { 233 Path tmpPath; 234 if (tmpPath.set(LLVM_LIBDIR)) 235 if (tmpPath.canRead()) 236 Paths.push_back(tmpPath); 237 } 238#endif 239 GetSystemLibraryPaths(Paths); 240} 241 242Path 243Path::GetUserHomeDirectory() { 244 const char* home = getenv("HOME"); 245 Path result; 246 if (home && result.set(home)) 247 return result; 248 result.set("/"); 249 return result; 250} 251 252Path 253Path::GetCurrentDirectory() { 254 char pathname[MAXPATHLEN]; 255 if (!getcwd(pathname, MAXPATHLEN)) { 256 assert(false && "Could not query current working directory."); 257 return Path(); 258 } 259 260 return Path(pathname); 261} 262 263#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 264 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) || \ 265 defined(__linux__) || defined(__CYGWIN__) 266static int 267test_dir(char buf[PATH_MAX], char ret[PATH_MAX], 268 const char *dir, const char *bin) 269{ 270 struct stat sb; 271 272 snprintf(buf, PATH_MAX, "%s/%s", dir, bin); 273 if (realpath(buf, ret) == NULL) 274 return (1); 275 if (stat(buf, &sb) != 0) 276 return (1); 277 278 return (0); 279} 280 281static char * 282getprogpath(char ret[PATH_MAX], const char *bin) 283{ 284 char *pv, *s, *t, buf[PATH_MAX]; 285 286 /* First approach: absolute path. */ 287 if (bin[0] == '/') { 288 if (test_dir(buf, ret, "/", bin) == 0) 289 return (ret); 290 return (NULL); 291 } 292 293 /* Second approach: relative path. */ 294 if (strchr(bin, '/') != NULL) { 295 if (getcwd(buf, PATH_MAX) == NULL) 296 return (NULL); 297 if (test_dir(buf, ret, buf, bin) == 0) 298 return (ret); 299 return (NULL); 300 } 301 302 /* Third approach: $PATH */ 303 if ((pv = getenv("PATH")) == NULL) 304 return (NULL); 305 s = pv = strdup(pv); 306 if (pv == NULL) 307 return (NULL); 308 while ((t = strsep(&s, ":")) != NULL) { 309 if (test_dir(buf, ret, t, bin) == 0) { 310 free(pv); 311 return (ret); 312 } 313 } 314 free(pv); 315 return (NULL); 316} 317#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ 318 319/// GetMainExecutable - Return the path to the main executable, given the 320/// value of argv[0] from program startup. 321Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { 322#if defined(__APPLE__) 323 // On OS X the executable path is saved to the stack by dyld. Reading it 324 // from there is much faster than calling dladdr, especially for large 325 // binaries with symbols. 326 char exe_path[MAXPATHLEN]; 327 uint32_t size = sizeof(exe_path); 328 if (_NSGetExecutablePath(exe_path, &size) == 0) { 329 char link_path[MAXPATHLEN]; 330 if (realpath(exe_path, link_path)) 331 return Path(link_path); 332 } 333#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ 334 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) 335 char exe_path[PATH_MAX]; 336 337 if (getprogpath(exe_path, argv0) != NULL) 338 return Path(exe_path); 339#elif defined(__linux__) || defined(__CYGWIN__) 340 char exe_path[MAXPATHLEN]; 341 StringRef aPath("/proc/self/exe"); 342 if (sys::fs::exists(aPath)) { 343 // /proc is not always mounted under Linux (chroot for example). 344 ssize_t len = readlink(aPath.str().c_str(), exe_path, sizeof(exe_path)); 345 if (len >= 0) 346 return Path(StringRef(exe_path, len)); 347 } else { 348 // Fall back to the classical detection. 349 if (getprogpath(exe_path, argv0) != NULL) 350 return Path(exe_path); 351 } 352#elif defined(HAVE_DLFCN_H) 353 // Use dladdr to get executable path if available. 354 Dl_info DLInfo; 355 int err = dladdr(MainAddr, &DLInfo); 356 if (err == 0) 357 return Path(); 358 359 // If the filename is a symlink, we need to resolve and return the location of 360 // the actual executable. 361 char link_path[MAXPATHLEN]; 362 if (realpath(DLInfo.dli_fname, link_path)) 363 return Path(link_path); 364#else 365#error GetMainExecutable is not implemented on this host yet. 366#endif 367 return Path(); 368} 369 370 371StringRef Path::getDirname() const { 372 return getDirnameCharSep(path, "/"); 373} 374 375StringRef 376Path::getBasename() const { 377 // Find the last slash 378 std::string::size_type slash = path.rfind('/'); 379 if (slash == std::string::npos) 380 slash = 0; 381 else 382 slash++; 383 384 std::string::size_type dot = path.rfind('.'); 385 if (dot == std::string::npos || dot < slash) 386 return StringRef(path).substr(slash); 387 else 388 return StringRef(path).substr(slash, dot - slash); 389} 390 391StringRef 392Path::getSuffix() const { 393 // Find the last slash 394 std::string::size_type slash = path.rfind('/'); 395 if (slash == std::string::npos) 396 slash = 0; 397 else 398 slash++; 399 400 std::string::size_type dot = path.rfind('.'); 401 if (dot == std::string::npos || dot < slash) 402 return StringRef(); 403 else 404 return StringRef(path).substr(dot + 1); 405} 406 407bool Path::getMagicNumber(std::string &Magic, unsigned len) const { 408 assert(len < 1024 && "Request for magic string too long"); 409 char Buf[1025]; 410 int fd = ::open(path.c_str(), O_RDONLY); 411 if (fd < 0) 412 return false; 413 ssize_t bytes_read = ::read(fd, Buf, len); 414 ::close(fd); 415 if (ssize_t(len) != bytes_read) 416 return false; 417 Magic.assign(Buf, len); 418 return true; 419} 420 421bool 422Path::exists() const { 423 return 0 == access(path.c_str(), F_OK ); 424} 425 426bool 427Path::isDirectory() const { 428 struct stat buf; 429 if (0 != stat(path.c_str(), &buf)) 430 return false; 431 return ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false; 432} 433 434bool 435Path::isSymLink() const { 436 struct stat buf; 437 if (0 != lstat(path.c_str(), &buf)) 438 return false; 439 return S_ISLNK(buf.st_mode); 440} 441 442 443bool 444Path::canRead() const { 445 return 0 == access(path.c_str(), R_OK); 446} 447 448bool 449Path::canWrite() const { 450 return 0 == access(path.c_str(), W_OK); 451} 452 453bool 454Path::isRegularFile() const { 455 // Get the status so we can determine if it's a file or directory 456 struct stat buf; 457 458 if (0 != stat(path.c_str(), &buf)) 459 return false; 460 461 if (S_ISREG(buf.st_mode)) 462 return true; 463 464 return false; 465} 466 467bool 468Path::canExecute() const { 469 if (0 != access(path.c_str(), R_OK | X_OK )) 470 return false; 471 struct stat buf; 472 if (0 != stat(path.c_str(), &buf)) 473 return false; 474 if (!S_ISREG(buf.st_mode)) 475 return false; 476 return true; 477} 478 479StringRef 480Path::getLast() const { 481 // Find the last slash 482 size_t pos = path.rfind('/'); 483 484 // Handle the corner cases 485 if (pos == std::string::npos) 486 return path; 487 488 // If the last character is a slash 489 if (pos == path.length()-1) { 490 // Find the second to last slash 491 size_t pos2 = path.rfind('/', pos-1); 492 if (pos2 == std::string::npos) 493 return StringRef(path).substr(0,pos); 494 else 495 return StringRef(path).substr(pos2+1,pos-pos2-1); 496 } 497 // Return everything after the last slash 498 return StringRef(path).substr(pos+1); 499} 500 501const FileStatus * 502PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const { 503 if (!fsIsValid || update) { 504 struct stat buf; 505 if (0 != stat(path.c_str(), &buf)) { 506 MakeErrMsg(ErrStr, path + ": can't get status of file"); 507 return 0; 508 } 509 status.fileSize = buf.st_size; 510 status.modTime.fromEpochTime(buf.st_mtime); 511 status.mode = buf.st_mode; 512 status.user = buf.st_uid; 513 status.group = buf.st_gid; 514 status.uniqueID = uint64_t(buf.st_ino); 515 status.isDir = S_ISDIR(buf.st_mode); 516 status.isFile = S_ISREG(buf.st_mode); 517 fsIsValid = true; 518 } 519 return &status; 520} 521 522static bool AddPermissionBits(const Path &File, int bits) { 523 // Get the umask value from the operating system. We want to use it 524 // when changing the file's permissions. Since calling umask() sets 525 // the umask and returns its old value, we must call it a second 526 // time to reset it to the user's preference. 527 int mask = umask(0777); // The arg. to umask is arbitrary. 528 umask(mask); // Restore the umask. 529 530 // Get the file's current mode. 531 struct stat buf; 532 if (0 != stat(File.c_str(), &buf)) 533 return false; 534 // Change the file to have whichever permissions bits from 'bits' 535 // that the umask would not disable. 536 if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1) 537 return false; 538 return true; 539} 540 541bool Path::makeReadableOnDisk(std::string* ErrMsg) { 542 if (!AddPermissionBits(*this, 0444)) 543 return MakeErrMsg(ErrMsg, path + ": can't make file readable"); 544 return false; 545} 546 547bool Path::makeWriteableOnDisk(std::string* ErrMsg) { 548 if (!AddPermissionBits(*this, 0222)) 549 return MakeErrMsg(ErrMsg, path + ": can't make file writable"); 550 return false; 551} 552 553bool Path::makeExecutableOnDisk(std::string* ErrMsg) { 554 if (!AddPermissionBits(*this, 0111)) 555 return MakeErrMsg(ErrMsg, path + ": can't make file executable"); 556 return false; 557} 558 559bool 560Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const { 561 DIR* direntries = ::opendir(path.c_str()); 562 if (direntries == 0) 563 return MakeErrMsg(ErrMsg, path + ": can't open directory"); 564 565 std::string dirPath = path; 566 if (!lastIsSlash(dirPath)) 567 dirPath += '/'; 568 569 result.clear(); 570 struct dirent* de = ::readdir(direntries); 571 for ( ; de != 0; de = ::readdir(direntries)) { 572 if (de->d_name[0] != '.') { 573 Path aPath(dirPath + (const char*)de->d_name); 574 struct stat st; 575 if (0 != lstat(aPath.path.c_str(), &st)) { 576 if (S_ISLNK(st.st_mode)) 577 continue; // dangling symlink -- ignore 578 return MakeErrMsg(ErrMsg, 579 aPath.path + ": can't determine file object type"); 580 } 581 result.insert(aPath); 582 } 583 } 584 585 closedir(direntries); 586 return false; 587} 588 589bool 590Path::set(StringRef a_path) { 591 if (a_path.empty()) 592 return false; 593 path = a_path; 594 return true; 595} 596 597bool 598Path::appendComponent(StringRef name) { 599 if (name.empty()) 600 return false; 601 if (!lastIsSlash(path)) 602 path += '/'; 603 path += name; 604 return true; 605} 606 607bool 608Path::eraseComponent() { 609 size_t slashpos = path.rfind('/',path.size()); 610 if (slashpos == 0 || slashpos == std::string::npos) { 611 path.erase(); 612 return true; 613 } 614 if (slashpos == path.size() - 1) 615 slashpos = path.rfind('/',slashpos-1); 616 if (slashpos == std::string::npos) { 617 path.erase(); 618 return true; 619 } 620 path.erase(slashpos); 621 return true; 622} 623 624bool 625Path::eraseSuffix() { 626 size_t dotpos = path.rfind('.',path.size()); 627 size_t slashpos = path.rfind('/',path.size()); 628 if (dotpos != std::string::npos) { 629 if (slashpos == std::string::npos || dotpos > slashpos+1) { 630 path.erase(dotpos, path.size()-dotpos); 631 return true; 632 } 633 } 634 return false; 635} 636 637static bool createDirectoryHelper(char* beg, char* end, bool create_parents) { 638 639 if (access(beg, R_OK | W_OK) == 0) 640 return false; 641 642 if (create_parents) { 643 644 char* c = end; 645 646 for (; c != beg; --c) 647 if (*c == '/') { 648 649 // Recurse to handling the parent directory. 650 *c = '\0'; 651 bool x = createDirectoryHelper(beg, c, create_parents); 652 *c = '/'; 653 654 // Return if we encountered an error. 655 if (x) 656 return true; 657 658 break; 659 } 660 } 661 662 return mkdir(beg, S_IRWXU | S_IRWXG) != 0; 663} 664 665bool 666Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) { 667 // Get a writeable copy of the path name 668 std::string pathname(path); 669 670 // Null-terminate the last component 671 size_t lastchar = path.length() - 1 ; 672 673 if (pathname[lastchar] != '/') 674 ++lastchar; 675 676 pathname[lastchar] = '\0'; 677 678 if (createDirectoryHelper(&pathname[0], &pathname[lastchar], create_parents)) 679 return MakeErrMsg(ErrMsg, pathname + ": can't create directory"); 680 681 return false; 682} 683 684bool 685Path::createFileOnDisk(std::string* ErrMsg) { 686 // Create the file 687 int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR); 688 if (fd < 0) 689 return MakeErrMsg(ErrMsg, path + ": can't create file"); 690 ::close(fd); 691 return false; 692} 693 694bool 695Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) { 696 // Make this into a unique file name 697 if (makeUnique( reuse_current, ErrMsg )) 698 return true; 699 700 // create the file 701 int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666); 702 if (fd < 0) 703 return MakeErrMsg(ErrMsg, path + ": can't create temporary file"); 704 ::close(fd); 705 return false; 706} 707 708bool 709Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const { 710 // Get the status so we can determine if it's a file or directory. 711 struct stat buf; 712 if (0 != stat(path.c_str(), &buf)) { 713 MakeErrMsg(ErrStr, path + ": can't get status of file"); 714 return true; 715 } 716 717 // Note: this check catches strange situations. In all cases, LLVM should 718 // only be involved in the creation and deletion of regular files. This 719 // check ensures that what we're trying to erase is a regular file. It 720 // effectively prevents LLVM from erasing things like /dev/null, any block 721 // special file, or other things that aren't "regular" files. 722 if (S_ISREG(buf.st_mode)) { 723 if (unlink(path.c_str()) != 0) 724 return MakeErrMsg(ErrStr, path + ": can't destroy file"); 725 return false; 726 } 727 728 if (!S_ISDIR(buf.st_mode)) { 729 if (ErrStr) *ErrStr = "not a file or directory"; 730 return true; 731 } 732 733 if (remove_contents) { 734 // Recursively descend the directory to remove its contents. 735 std::string cmd = "/bin/rm -rf " + path; 736 if (system(cmd.c_str()) != 0) { 737 MakeErrMsg(ErrStr, path + ": failed to recursively remove directory."); 738 return true; 739 } 740 return false; 741 } 742 743 // Otherwise, try to just remove the one directory. 744 std::string pathname(path); 745 size_t lastchar = path.length() - 1; 746 if (pathname[lastchar] == '/') 747 pathname[lastchar] = '\0'; 748 else 749 pathname[lastchar+1] = '\0'; 750 751 if (rmdir(pathname.c_str()) != 0) 752 return MakeErrMsg(ErrStr, pathname + ": can't erase directory"); 753 return false; 754} 755 756bool 757Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) { 758 if (0 != ::rename(path.c_str(), newName.c_str())) 759 return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" + 760 newName.str() + "'"); 761 return false; 762} 763 764bool 765Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const { 766 struct utimbuf utb; 767 utb.actime = si.modTime.toPosixTime(); 768 utb.modtime = utb.actime; 769 if (0 != ::utime(path.c_str(),&utb)) 770 return MakeErrMsg(ErrStr, path + ": can't set file modification time"); 771 if (0 != ::chmod(path.c_str(),si.mode)) 772 return MakeErrMsg(ErrStr, path + ": can't set mode"); 773 return false; 774} 775 776bool 777sys::CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg){ 778 int inFile = -1; 779 int outFile = -1; 780 inFile = ::open(Src.c_str(), O_RDONLY); 781 if (inFile == -1) 782 return MakeErrMsg(ErrMsg, Src.str() + 783 ": can't open source file to copy"); 784 785 outFile = ::open(Dest.c_str(), O_WRONLY|O_CREAT, 0666); 786 if (outFile == -1) { 787 ::close(inFile); 788 return MakeErrMsg(ErrMsg, Dest.str() + 789 ": can't create destination file for copy"); 790 } 791 792 char Buffer[16*1024]; 793 while (ssize_t Amt = ::read(inFile, Buffer, 16*1024)) { 794 if (Amt == -1) { 795 if (errno != EINTR && errno != EAGAIN) { 796 ::close(inFile); 797 ::close(outFile); 798 return MakeErrMsg(ErrMsg, Src.str()+": can't read source file"); 799 } 800 } else { 801 char *BufPtr = Buffer; 802 while (Amt) { 803 ssize_t AmtWritten = ::write(outFile, BufPtr, Amt); 804 if (AmtWritten == -1) { 805 if (errno != EINTR && errno != EAGAIN) { 806 ::close(inFile); 807 ::close(outFile); 808 return MakeErrMsg(ErrMsg, Dest.str() + 809 ": can't write destination file"); 810 } 811 } else { 812 Amt -= AmtWritten; 813 BufPtr += AmtWritten; 814 } 815 } 816 } 817 } 818 ::close(inFile); 819 ::close(outFile); 820 return false; 821} 822 823bool 824Path::makeUnique(bool reuse_current, std::string* ErrMsg) { 825 bool Exists; 826 if (reuse_current && (fs::exists(path, Exists) || !Exists)) 827 return false; // File doesn't exist already, just use it! 828 829 // Append an XXXXXX pattern to the end of the file for use with mkstemp, 830 // mktemp or our own implementation. 831 // This uses std::vector instead of SmallVector to avoid a dependence on 832 // libSupport. And performance isn't critical here. 833 std::vector<char> Buf; 834 Buf.resize(path.size()+8); 835 char *FNBuffer = &Buf[0]; 836 path.copy(FNBuffer,path.size()); 837 bool isdir; 838 if (!fs::is_directory(path, isdir) && isdir) 839 strcpy(FNBuffer+path.size(), "/XXXXXX"); 840 else 841 strcpy(FNBuffer+path.size(), "-XXXXXX"); 842 843#if defined(HAVE_MKSTEMP) 844 int TempFD; 845 if ((TempFD = mkstemp(FNBuffer)) == -1) 846 return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); 847 848 // We don't need to hold the temp file descriptor... we will trust that no one 849 // will overwrite/delete the file before we can open it again. 850 close(TempFD); 851 852 // Save the name 853 path = FNBuffer; 854 855 // By default mkstemp sets the mode to 0600, so update mode bits now. 856 AddPermissionBits (*this, 0666); 857#elif defined(HAVE_MKTEMP) 858 // If we don't have mkstemp, use the old and obsolete mktemp function. 859 if (mktemp(FNBuffer) == 0) 860 return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); 861 862 // Save the name 863 path = FNBuffer; 864#else 865 // Okay, looks like we have to do it all by our lonesome. 866 static unsigned FCounter = 0; 867 // Try to initialize with unique value. 868 if (FCounter == 0) FCounter = ((unsigned)getpid() & 0xFFFF) << 8; 869 char* pos = strstr(FNBuffer, "XXXXXX"); 870 do { 871 if (++FCounter > 0xFFFFFF) { 872 return MakeErrMsg(ErrMsg, 873 path + ": can't make unique filename: too many files"); 874 } 875 sprintf(pos, "%06X", FCounter); 876 path = FNBuffer; 877 } while (exists()); 878 // POSSIBLE SECURITY BUG: An attacker can easily guess the name and exploit 879 // LLVM. 880#endif 881 return false; 882} 883 884const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) { 885 int Flags = MAP_PRIVATE; 886#ifdef MAP_FILE 887 Flags |= MAP_FILE; 888#endif 889 void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, Offset); 890 if (BasePtr == MAP_FAILED) 891 return 0; 892 return (const char*)BasePtr; 893} 894 895void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) { 896 const void *Addr = static_cast<const void *>(BasePtr); 897 ::munmap(const_cast<void *>(Addr), FileSize); 898} 899 900} // end llvm namespace 901