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__) || \ 264 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) 265static int 266test_dir(char buf[PATH_MAX], char ret[PATH_MAX], 267 const char *dir, const char *bin) 268{ 269 struct stat sb; 270 271 snprintf(buf, PATH_MAX, "%s/%s", dir, bin); 272 if (realpath(buf, ret) == NULL) 273 return (1); 274 if (stat(buf, &sb) != 0) 275 return (1); 276 277 return (0); 278} 279 280static char * 281getprogpath(char ret[PATH_MAX], const char *bin) 282{ 283 char *pv, *s, *t, buf[PATH_MAX]; 284 285 /* First approach: absolute path. */ 286 if (bin[0] == '/') { 287 if (test_dir(buf, ret, "/", bin) == 0) 288 return (ret); 289 return (NULL); 290 } 291 292 /* Second approach: relative path. */ 293 if (strchr(bin, '/') != NULL) { 294 if (getcwd(buf, PATH_MAX) == NULL) 295 return (NULL); 296 if (test_dir(buf, ret, buf, bin) == 0) 297 return (ret); 298 return (NULL); 299 } 300 301 /* Third approach: $PATH */ 302 if ((pv = getenv("PATH")) == NULL) 303 return (NULL); 304 s = pv = strdup(pv); 305 if (pv == NULL) 306 return (NULL); 307 while ((t = strsep(&s, ":")) != NULL) { 308 if (test_dir(buf, ret, t, bin) == 0) { 309 free(pv); 310 return (ret); 311 } 312 } 313 free(pv); 314 return (NULL); 315} 316#endif // __FreeBSD__ || __NetBSD__ || __FreeBSD_kernel__ 317 318/// GetMainExecutable - Return the path to the main executable, given the 319/// value of argv[0] from program startup. 320Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { 321#if defined(__APPLE__) 322 // On OS X the executable path is saved to the stack by dyld. Reading it 323 // from there is much faster than calling dladdr, especially for large 324 // binaries with symbols. 325 char exe_path[MAXPATHLEN]; 326 uint32_t size = sizeof(exe_path); 327 if (_NSGetExecutablePath(exe_path, &size) == 0) { 328 char link_path[MAXPATHLEN]; 329 if (realpath(exe_path, link_path)) 330 return Path(link_path); 331 } 332#elif defined(__FreeBSD__) || defined (__NetBSD__) || \ 333 defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) 334 char exe_path[PATH_MAX]; 335 336 if (getprogpath(exe_path, argv0) != NULL) 337 return Path(exe_path); 338#elif defined(__linux__) || defined(__CYGWIN__) 339 char exe_path[MAXPATHLEN]; 340 ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path)); 341 if (len >= 0) 342 return Path(StringRef(exe_path, len)); 343#elif defined(HAVE_DLFCN_H) 344 // Use dladdr to get executable path if available. 345 Dl_info DLInfo; 346 int err = dladdr(MainAddr, &DLInfo); 347 if (err == 0) 348 return Path(); 349 350 // If the filename is a symlink, we need to resolve and return the location of 351 // the actual executable. 352 char link_path[MAXPATHLEN]; 353 if (realpath(DLInfo.dli_fname, link_path)) 354 return Path(link_path); 355#else 356#error GetMainExecutable is not implemented on this host yet. 357#endif 358 return Path(); 359} 360 361 362StringRef Path::getDirname() const { 363 return getDirnameCharSep(path, "/"); 364} 365 366StringRef 367Path::getBasename() const { 368 // Find the last slash 369 std::string::size_type slash = path.rfind('/'); 370 if (slash == std::string::npos) 371 slash = 0; 372 else 373 slash++; 374 375 std::string::size_type dot = path.rfind('.'); 376 if (dot == std::string::npos || dot < slash) 377 return StringRef(path).substr(slash); 378 else 379 return StringRef(path).substr(slash, dot - slash); 380} 381 382StringRef 383Path::getSuffix() const { 384 // Find the last slash 385 std::string::size_type slash = path.rfind('/'); 386 if (slash == std::string::npos) 387 slash = 0; 388 else 389 slash++; 390 391 std::string::size_type dot = path.rfind('.'); 392 if (dot == std::string::npos || dot < slash) 393 return StringRef(); 394 else 395 return StringRef(path).substr(dot + 1); 396} 397 398bool Path::getMagicNumber(std::string &Magic, unsigned len) const { 399 assert(len < 1024 && "Request for magic string too long"); 400 char Buf[1025]; 401 int fd = ::open(path.c_str(), O_RDONLY); 402 if (fd < 0) 403 return false; 404 ssize_t bytes_read = ::read(fd, Buf, len); 405 ::close(fd); 406 if (ssize_t(len) != bytes_read) 407 return false; 408 Magic.assign(Buf, len); 409 return true; 410} 411 412bool 413Path::exists() const { 414 return 0 == access(path.c_str(), F_OK ); 415} 416 417bool 418Path::isDirectory() const { 419 struct stat buf; 420 if (0 != stat(path.c_str(), &buf)) 421 return false; 422 return ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false; 423} 424 425bool 426Path::isSymLink() const { 427 struct stat buf; 428 if (0 != lstat(path.c_str(), &buf)) 429 return false; 430 return S_ISLNK(buf.st_mode); 431} 432 433 434bool 435Path::canRead() const { 436 return 0 == access(path.c_str(), R_OK); 437} 438 439bool 440Path::canWrite() const { 441 return 0 == access(path.c_str(), W_OK); 442} 443 444bool 445Path::isRegularFile() const { 446 // Get the status so we can determine if it's a file or directory 447 struct stat buf; 448 449 if (0 != stat(path.c_str(), &buf)) 450 return false; 451 452 if (S_ISREG(buf.st_mode)) 453 return true; 454 455 return false; 456} 457 458bool 459Path::canExecute() const { 460 if (0 != access(path.c_str(), R_OK | X_OK )) 461 return false; 462 struct stat buf; 463 if (0 != stat(path.c_str(), &buf)) 464 return false; 465 if (!S_ISREG(buf.st_mode)) 466 return false; 467 return true; 468} 469 470StringRef 471Path::getLast() const { 472 // Find the last slash 473 size_t pos = path.rfind('/'); 474 475 // Handle the corner cases 476 if (pos == std::string::npos) 477 return path; 478 479 // If the last character is a slash 480 if (pos == path.length()-1) { 481 // Find the second to last slash 482 size_t pos2 = path.rfind('/', pos-1); 483 if (pos2 == std::string::npos) 484 return StringRef(path).substr(0,pos); 485 else 486 return StringRef(path).substr(pos2+1,pos-pos2-1); 487 } 488 // Return everything after the last slash 489 return StringRef(path).substr(pos+1); 490} 491 492const FileStatus * 493PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const { 494 if (!fsIsValid || update) { 495 struct stat buf; 496 if (0 != stat(path.c_str(), &buf)) { 497 MakeErrMsg(ErrStr, path + ": can't get status of file"); 498 return 0; 499 } 500 status.fileSize = buf.st_size; 501 status.modTime.fromEpochTime(buf.st_mtime); 502 status.mode = buf.st_mode; 503 status.user = buf.st_uid; 504 status.group = buf.st_gid; 505 status.uniqueID = uint64_t(buf.st_ino); 506 status.isDir = S_ISDIR(buf.st_mode); 507 status.isFile = S_ISREG(buf.st_mode); 508 fsIsValid = true; 509 } 510 return &status; 511} 512 513static bool AddPermissionBits(const Path &File, int bits) { 514 // Get the umask value from the operating system. We want to use it 515 // when changing the file's permissions. Since calling umask() sets 516 // the umask and returns its old value, we must call it a second 517 // time to reset it to the user's preference. 518 int mask = umask(0777); // The arg. to umask is arbitrary. 519 umask(mask); // Restore the umask. 520 521 // Get the file's current mode. 522 struct stat buf; 523 if (0 != stat(File.c_str(), &buf)) 524 return false; 525 // Change the file to have whichever permissions bits from 'bits' 526 // that the umask would not disable. 527 if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1) 528 return false; 529 return true; 530} 531 532bool Path::makeReadableOnDisk(std::string* ErrMsg) { 533 if (!AddPermissionBits(*this, 0444)) 534 return MakeErrMsg(ErrMsg, path + ": can't make file readable"); 535 return false; 536} 537 538bool Path::makeWriteableOnDisk(std::string* ErrMsg) { 539 if (!AddPermissionBits(*this, 0222)) 540 return MakeErrMsg(ErrMsg, path + ": can't make file writable"); 541 return false; 542} 543 544bool Path::makeExecutableOnDisk(std::string* ErrMsg) { 545 if (!AddPermissionBits(*this, 0111)) 546 return MakeErrMsg(ErrMsg, path + ": can't make file executable"); 547 return false; 548} 549 550bool 551Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const { 552 DIR* direntries = ::opendir(path.c_str()); 553 if (direntries == 0) 554 return MakeErrMsg(ErrMsg, path + ": can't open directory"); 555 556 std::string dirPath = path; 557 if (!lastIsSlash(dirPath)) 558 dirPath += '/'; 559 560 result.clear(); 561 struct dirent* de = ::readdir(direntries); 562 for ( ; de != 0; de = ::readdir(direntries)) { 563 if (de->d_name[0] != '.') { 564 Path aPath(dirPath + (const char*)de->d_name); 565 struct stat st; 566 if (0 != lstat(aPath.path.c_str(), &st)) { 567 if (S_ISLNK(st.st_mode)) 568 continue; // dangling symlink -- ignore 569 return MakeErrMsg(ErrMsg, 570 aPath.path + ": can't determine file object type"); 571 } 572 result.insert(aPath); 573 } 574 } 575 576 closedir(direntries); 577 return false; 578} 579 580bool 581Path::set(StringRef a_path) { 582 if (a_path.empty()) 583 return false; 584 path = a_path; 585 return true; 586} 587 588bool 589Path::appendComponent(StringRef name) { 590 if (name.empty()) 591 return false; 592 if (!lastIsSlash(path)) 593 path += '/'; 594 path += name; 595 return true; 596} 597 598bool 599Path::eraseComponent() { 600 size_t slashpos = path.rfind('/',path.size()); 601 if (slashpos == 0 || slashpos == std::string::npos) { 602 path.erase(); 603 return true; 604 } 605 if (slashpos == path.size() - 1) 606 slashpos = path.rfind('/',slashpos-1); 607 if (slashpos == std::string::npos) { 608 path.erase(); 609 return true; 610 } 611 path.erase(slashpos); 612 return true; 613} 614 615bool 616Path::eraseSuffix() { 617 size_t dotpos = path.rfind('.',path.size()); 618 size_t slashpos = path.rfind('/',path.size()); 619 if (dotpos != std::string::npos) { 620 if (slashpos == std::string::npos || dotpos > slashpos+1) { 621 path.erase(dotpos, path.size()-dotpos); 622 return true; 623 } 624 } 625 return false; 626} 627 628static bool createDirectoryHelper(char* beg, char* end, bool create_parents) { 629 630 if (access(beg, R_OK | W_OK) == 0) 631 return false; 632 633 if (create_parents) { 634 635 char* c = end; 636 637 for (; c != beg; --c) 638 if (*c == '/') { 639 640 // Recurse to handling the parent directory. 641 *c = '\0'; 642 bool x = createDirectoryHelper(beg, c, create_parents); 643 *c = '/'; 644 645 // Return if we encountered an error. 646 if (x) 647 return true; 648 649 break; 650 } 651 } 652 653 return mkdir(beg, S_IRWXU | S_IRWXG) != 0; 654} 655 656bool 657Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) { 658 // Get a writeable copy of the path name 659 std::string pathname(path); 660 661 // Null-terminate the last component 662 size_t lastchar = path.length() - 1 ; 663 664 if (pathname[lastchar] != '/') 665 ++lastchar; 666 667 pathname[lastchar] = '\0'; 668 669 if (createDirectoryHelper(&pathname[0], &pathname[lastchar], create_parents)) 670 return MakeErrMsg(ErrMsg, pathname + ": can't create directory"); 671 672 return false; 673} 674 675bool 676Path::createFileOnDisk(std::string* ErrMsg) { 677 // Create the file 678 int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR); 679 if (fd < 0) 680 return MakeErrMsg(ErrMsg, path + ": can't create file"); 681 ::close(fd); 682 return false; 683} 684 685bool 686Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) { 687 // Make this into a unique file name 688 if (makeUnique( reuse_current, ErrMsg )) 689 return true; 690 691 // create the file 692 int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666); 693 if (fd < 0) 694 return MakeErrMsg(ErrMsg, path + ": can't create temporary file"); 695 ::close(fd); 696 return false; 697} 698 699bool 700Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const { 701 // Get the status so we can determine if it's a file or directory. 702 struct stat buf; 703 if (0 != stat(path.c_str(), &buf)) { 704 MakeErrMsg(ErrStr, path + ": can't get status of file"); 705 return true; 706 } 707 708 // Note: this check catches strange situations. In all cases, LLVM should 709 // only be involved in the creation and deletion of regular files. This 710 // check ensures that what we're trying to erase is a regular file. It 711 // effectively prevents LLVM from erasing things like /dev/null, any block 712 // special file, or other things that aren't "regular" files. 713 if (S_ISREG(buf.st_mode)) { 714 if (unlink(path.c_str()) != 0) 715 return MakeErrMsg(ErrStr, path + ": can't destroy file"); 716 return false; 717 } 718 719 if (!S_ISDIR(buf.st_mode)) { 720 if (ErrStr) *ErrStr = "not a file or directory"; 721 return true; 722 } 723 724 if (remove_contents) { 725 // Recursively descend the directory to remove its contents. 726 std::string cmd = "/bin/rm -rf " + path; 727 if (system(cmd.c_str()) != 0) { 728 MakeErrMsg(ErrStr, path + ": failed to recursively remove directory."); 729 return true; 730 } 731 return false; 732 } 733 734 // Otherwise, try to just remove the one directory. 735 std::string pathname(path); 736 size_t lastchar = path.length() - 1; 737 if (pathname[lastchar] == '/') 738 pathname[lastchar] = '\0'; 739 else 740 pathname[lastchar+1] = '\0'; 741 742 if (rmdir(pathname.c_str()) != 0) 743 return MakeErrMsg(ErrStr, pathname + ": can't erase directory"); 744 return false; 745} 746 747bool 748Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) { 749 if (0 != ::rename(path.c_str(), newName.c_str())) 750 return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" + 751 newName.str() + "'"); 752 return false; 753} 754 755bool 756Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const { 757 struct utimbuf utb; 758 utb.actime = si.modTime.toPosixTime(); 759 utb.modtime = utb.actime; 760 if (0 != ::utime(path.c_str(),&utb)) 761 return MakeErrMsg(ErrStr, path + ": can't set file modification time"); 762 if (0 != ::chmod(path.c_str(),si.mode)) 763 return MakeErrMsg(ErrStr, path + ": can't set mode"); 764 return false; 765} 766 767bool 768sys::CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg){ 769 int inFile = -1; 770 int outFile = -1; 771 inFile = ::open(Src.c_str(), O_RDONLY); 772 if (inFile == -1) 773 return MakeErrMsg(ErrMsg, Src.str() + 774 ": can't open source file to copy"); 775 776 outFile = ::open(Dest.c_str(), O_WRONLY|O_CREAT, 0666); 777 if (outFile == -1) { 778 ::close(inFile); 779 return MakeErrMsg(ErrMsg, Dest.str() + 780 ": can't create destination file for copy"); 781 } 782 783 char Buffer[16*1024]; 784 while (ssize_t Amt = ::read(inFile, Buffer, 16*1024)) { 785 if (Amt == -1) { 786 if (errno != EINTR && errno != EAGAIN) { 787 ::close(inFile); 788 ::close(outFile); 789 return MakeErrMsg(ErrMsg, Src.str()+": can't read source file"); 790 } 791 } else { 792 char *BufPtr = Buffer; 793 while (Amt) { 794 ssize_t AmtWritten = ::write(outFile, BufPtr, Amt); 795 if (AmtWritten == -1) { 796 if (errno != EINTR && errno != EAGAIN) { 797 ::close(inFile); 798 ::close(outFile); 799 return MakeErrMsg(ErrMsg, Dest.str() + 800 ": can't write destination file"); 801 } 802 } else { 803 Amt -= AmtWritten; 804 BufPtr += AmtWritten; 805 } 806 } 807 } 808 } 809 ::close(inFile); 810 ::close(outFile); 811 return false; 812} 813 814bool 815Path::makeUnique(bool reuse_current, std::string* ErrMsg) { 816 bool Exists; 817 if (reuse_current && (fs::exists(path, Exists) || !Exists)) 818 return false; // File doesn't exist already, just use it! 819 820 // Append an XXXXXX pattern to the end of the file for use with mkstemp, 821 // mktemp or our own implementation. 822 // This uses std::vector instead of SmallVector to avoid a dependence on 823 // libSupport. And performance isn't critical here. 824 std::vector<char> Buf; 825 Buf.resize(path.size()+8); 826 char *FNBuffer = &Buf[0]; 827 path.copy(FNBuffer,path.size()); 828 bool isdir; 829 if (!fs::is_directory(path, isdir) && isdir) 830 strcpy(FNBuffer+path.size(), "/XXXXXX"); 831 else 832 strcpy(FNBuffer+path.size(), "-XXXXXX"); 833 834#if defined(HAVE_MKSTEMP) 835 int TempFD; 836 if ((TempFD = mkstemp(FNBuffer)) == -1) 837 return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); 838 839 // We don't need to hold the temp file descriptor... we will trust that no one 840 // will overwrite/delete the file before we can open it again. 841 close(TempFD); 842 843 // Save the name 844 path = FNBuffer; 845 846 // By default mkstemp sets the mode to 0600, so update mode bits now. 847 AddPermissionBits (*this, 0666); 848#elif defined(HAVE_MKTEMP) 849 // If we don't have mkstemp, use the old and obsolete mktemp function. 850 if (mktemp(FNBuffer) == 0) 851 return MakeErrMsg(ErrMsg, path + ": can't make unique filename"); 852 853 // Save the name 854 path = FNBuffer; 855#else 856 // Okay, looks like we have to do it all by our lonesome. 857 static unsigned FCounter = 0; 858 // Try to initialize with unique value. 859 if (FCounter == 0) FCounter = ((unsigned)getpid() & 0xFFFF) << 8; 860 char* pos = strstr(FNBuffer, "XXXXXX"); 861 do { 862 if (++FCounter > 0xFFFFFF) { 863 return MakeErrMsg(ErrMsg, 864 path + ": can't make unique filename: too many files"); 865 } 866 sprintf(pos, "%06X", FCounter); 867 path = FNBuffer; 868 } while (exists()); 869 // POSSIBLE SECURITY BUG: An attacker can easily guess the name and exploit 870 // LLVM. 871#endif 872 return false; 873} 874 875const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) { 876 int Flags = MAP_PRIVATE; 877#ifdef MAP_FILE 878 Flags |= MAP_FILE; 879#endif 880 void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, Offset); 881 if (BasePtr == MAP_FAILED) 882 return 0; 883 return (const char*)BasePtr; 884} 885 886void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) { 887 ::munmap((void*)BasePtr, FileSize); 888} 889 890} // end llvm namespace 891