diff options
author | dim <dim@FreeBSD.org> | 2012-08-15 19:34:23 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-08-15 19:34:23 +0000 |
commit | 721c201bd55ffb73cb2ba8d39e0570fa38c44e15 (patch) | |
tree | eacfc83d988e4b9d11114387ae7dc41243f2a363 /lib/Support/Unix | |
parent | 2b2816e083a455f7a656ae88b0fd059d1688bb36 (diff) | |
download | FreeBSD-src-721c201bd55ffb73cb2ba8d39e0570fa38c44e15.zip FreeBSD-src-721c201bd55ffb73cb2ba8d39e0570fa38c44e15.tar.gz |
Vendor import of llvm trunk r161861:
http://llvm.org/svn/llvm-project/llvm/trunk@161861
Diffstat (limited to 'lib/Support/Unix')
-rw-r--r-- | lib/Support/Unix/Path.inc | 7 | ||||
-rw-r--r-- | lib/Support/Unix/PathV2.inc | 134 | ||||
-rw-r--r-- | lib/Support/Unix/Process.inc | 53 | ||||
-rw-r--r-- | lib/Support/Unix/Signals.inc | 50 | ||||
-rw-r--r-- | lib/Support/Unix/Unix.h | 10 |
5 files changed, 185 insertions, 69 deletions
diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc index ddc1e0f..6bddbdf 100644 --- a/lib/Support/Unix/Path.inc +++ b/lib/Support/Unix/Path.inc @@ -260,7 +260,7 @@ Path::GetCurrentDirectory() { return Path(pathname); } -#if defined(__FreeBSD__) || defined (__NetBSD__) || \ +#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) static int test_dir(char buf[PATH_MAX], char ret[PATH_MAX], @@ -329,7 +329,7 @@ Path Path::GetMainExecutable(const char *argv0, void *MainAddr) { if (realpath(exe_path, link_path)) return Path(link_path); } -#elif defined(__FreeBSD__) || defined (__NetBSD__) || \ +#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \ defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__) char exe_path[PATH_MAX]; @@ -884,7 +884,8 @@ const char *Path::MapInFilePages(int FD, size_t FileSize, off_t Offset) { } void Path::UnMapFilePages(const char *BasePtr, size_t FileSize) { - ::munmap((void*)BasePtr, FileSize); + const void *Addr = static_cast<const void *>(BasePtr); + ::munmap(const_cast<void *>(Addr), FileSize); } } // end llvm namespace diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index edb101e..99f8cd4 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -17,12 +17,16 @@ //===----------------------------------------------------------------------===// #include "Unix.h" +#include "llvm/Support/Process.h" #if HAVE_SYS_STAT_H #include <sys/stat.h> #endif #if HAVE_FCNTL_H #include <fcntl.h> #endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif #if HAVE_DIRENT_H # include <dirent.h> # define NAMLEN(dirent) strlen((dirent)->d_name) @@ -46,6 +50,12 @@ #include <limits.h> #endif +// Both stdio.h and cstdio are included via different pathes and +// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros +// either. +#undef ferror +#undef feof + // For GNU Hurd #if defined(__GNU__) && !defined(PATH_MAX) # define PATH_MAX 4096 @@ -272,8 +282,7 @@ error_code exists(const Twine &path, bool &result) { SmallString<128> path_storage; StringRef p = path.toNullTerminatedStringRef(path_storage); - struct stat status; - if (::stat(p.begin(), &status) == -1) { + if (::access(p.begin(), F_OK) == -1) { if (errno != errc::no_such_file_or_directory) return error_code(errno, system_category()); result = false; @@ -285,8 +294,8 @@ error_code exists(const Twine &path, bool &result) { bool equivalent(file_status A, file_status B) { assert(status_known(A) && status_known(B)); - return A.st_dev == B.st_dev && - A.st_ino == B.st_ino; + return A.fs_st_dev == B.fs_st_dev && + A.fs_st_ino == B.fs_st_ino; } error_code equivalent(const Twine &A, const Twine &B, bool &result) { @@ -325,30 +334,62 @@ error_code status(const Twine &path, file_status &result) { return ec; } + perms prms = static_cast<perms>(status.st_mode & perms_mask); + if (S_ISDIR(status.st_mode)) - result = file_status(file_type::directory_file); + result = file_status(file_type::directory_file, prms); else if (S_ISREG(status.st_mode)) - result = file_status(file_type::regular_file); + result = file_status(file_type::regular_file, prms); else if (S_ISBLK(status.st_mode)) - result = file_status(file_type::block_file); + result = file_status(file_type::block_file, prms); else if (S_ISCHR(status.st_mode)) - result = file_status(file_type::character_file); + result = file_status(file_type::character_file, prms); else if (S_ISFIFO(status.st_mode)) - result = file_status(file_type::fifo_file); + result = file_status(file_type::fifo_file, prms); else if (S_ISSOCK(status.st_mode)) - result = file_status(file_type::socket_file); + result = file_status(file_type::socket_file, prms); else - result = file_status(file_type::type_unknown); + result = file_status(file_type::type_unknown, prms); - result.st_dev = status.st_dev; - result.st_ino = status.st_ino; + result.fs_st_dev = status.st_dev; + result.fs_st_ino = status.st_ino; return error_code::success(); } +// Modifies permissions on a file. +error_code permissions(const Twine &path, perms prms) { + if ((prms & add_perms) && (prms & remove_perms)) + llvm_unreachable("add_perms and remove_perms are mutually exclusive"); + + // Get current permissions + file_status info; + if (error_code ec = status(path, info)) { + return ec; + } + + // Set updated permissions. + SmallString<128> path_storage; + StringRef p = path.toNullTerminatedStringRef(path_storage); + perms permsToSet; + if (prms & add_perms) { + permsToSet = (info.permissions() | prms) & perms_mask; + } else if (prms & remove_perms) { + permsToSet = (info.permissions() & ~prms) & perms_mask; + } else { + permsToSet = prms & perms_mask; + } + if (::chmod(p.begin(), static_cast<mode_t>(permsToSet))) { + return error_code(errno, system_category()); + } + + return error_code::success(); +} + +// Since this is most often used for temporary files, mode defaults to 0600. error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl<char> &result_path, - bool makeAbsolute) { + SmallVectorImpl<char> &result_path, + bool makeAbsolute, unsigned mode) { SmallString<128> Model; model.toVector(Model); // Null terminate. @@ -365,37 +406,20 @@ error_code unique_file(const Twine &model, int &result_fd, } } - // Replace '%' with random chars. From here on, DO NOT modify model. It may be - // needed if the randomly chosen path already exists. - SmallString<128> RandomPath; - RandomPath.reserve(Model.size() + 1); - ::srand(::time(NULL)); + // From here on, DO NOT modify model. It may be needed if the randomly chosen + // path already exists. + SmallString<128> RandomPath = Model; retry_random_path: - // This is opened here instead of above to make it easier to track when to - // close it. Collisions should be rare enough for the possible extra syscalls - // not to matter. - FILE *RandomSource = ::fopen("/dev/urandom", "r"); - RandomPath.set_size(0); - for (SmallVectorImpl<char>::const_iterator i = Model.begin(), - e = Model.end(); i != e; ++i) { - if (*i == '%') { - char val = 0; - if (RandomSource) - val = fgetc(RandomSource); - else - val = ::rand(); - RandomPath.push_back("0123456789abcdef"[val & 15]); - } else - RandomPath.push_back(*i); + // Replace '%' with random chars. + for (unsigned i = 0, e = Model.size(); i != e; ++i) { + if (Model[i] == '%') + RandomPath[i] = "0123456789abcdef"[sys::Process::GetRandomNumber() & 15]; } - if (RandomSource) - ::fclose(RandomSource); - // Try to open + create the file. rety_open_create: - int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); + int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, mode); if (RandomFD == -1) { // If the file existed, try again, otherwise, error. if (errno == errc::file_exists) @@ -511,6 +535,36 @@ error_code get_magic(const Twine &path, uint32_t len, return error_code::success(); } +error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, + bool map_writable, void *&result) { + SmallString<128> path_storage; + StringRef name = path.toNullTerminatedStringRef(path_storage); + int oflags = map_writable ? O_RDWR : O_RDONLY; + int ofd = ::open(name.begin(), oflags); + if ( ofd == -1 ) + return error_code(errno, system_category()); + AutoFD fd(ofd); + int flags = map_writable ? MAP_SHARED : MAP_PRIVATE; + int prot = map_writable ? (PROT_READ|PROT_WRITE) : PROT_READ; +#ifdef MAP_FILE + flags |= MAP_FILE; +#endif + result = ::mmap(0, size, prot, flags, fd, file_offset); + if (result == MAP_FAILED) { + return error_code(errno, system_category()); + } + + return error_code::success(); +} + +error_code unmap_file_pages(void *base, size_t size) { + if ( ::munmap(base, size) == -1 ) + return error_code(errno, system_category()); + + return error_code::success(); +} + + } // end namespace fs } // end namespace sys } // end namespace llvm diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index f640462..5204147 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -12,15 +12,18 @@ //===----------------------------------------------------------------------===// #include "Unix.h" +#include "llvm/ADT/Hashing.h" +#include "llvm/Support/TimeValue.h" #ifdef HAVE_SYS_TIME_H #include <sys/time.h> #endif #ifdef HAVE_SYS_RESOURCE_H #include <sys/resource.h> #endif -// DragonFly BSD has deprecated <malloc.h> for <stdlib.h> instead, -// Unix.h includes this for us already. -#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) +// DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for +// <stdlib.h> instead. Unix.h includes this for us already. +#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \ + !defined(__OpenBSD__) && !defined(__Bitrig__) #include <malloc.h> #endif #ifdef HAVE_MALLOC_MALLOC_H @@ -247,16 +250,18 @@ static bool terminalHasColors() { return false; } +bool Process::FileDescriptorHasColors(int fd) { + // A file descriptor has colors if it is displayed and the terminal has + // colors. + return FileDescriptorIsDisplayed(fd) && terminalHasColors(); +} + bool Process::StandardOutHasColors() { - if (!StandardOutIsDisplayed()) - return false; - return terminalHasColors(); + return FileDescriptorHasColors(STDOUT_FILENO); } bool Process::StandardErrHasColors() { - if (!StandardErrIsDisplayed()) - return false; - return terminalHasColors(); + return FileDescriptorHasColors(STDERR_FILENO); } bool Process::ColorNeedsFlush() { @@ -297,3 +302,33 @@ const char *Process::OutputReverse() { const char *Process::ResetColor() { return "\033[0m"; } + +#if !defined(HAVE_ARC4RANDOM) +static unsigned GetRandomNumberSeed() { + // Attempt to get the initial seed from /dev/urandom, if possible. + if (FILE *RandomSource = ::fopen("/dev/urandom", "r")) { + unsigned seed; + int count = ::fread((void *)&seed, sizeof(seed), 1, RandomSource); + ::fclose(RandomSource); + + // Return the seed if the read was successful. + if (count == 1) + return seed; + } + + // Otherwise, swizzle the current time and the process ID to form a reasonable + // seed. + TimeValue Now = llvm::TimeValue::now(); + return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid()); +} +#endif + +unsigned llvm::sys::Process::GetRandomNumber() { +#if defined(HAVE_ARC4RANDOM) + return arc4random(); +#else + static int x = (::srand(GetRandomNumberSeed()), 0); + (void)x; + return ::rand(); +#endif +} diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc index c9ec9fc..5195116 100644 --- a/lib/Support/Unix/Signals.inc +++ b/lib/Support/Unix/Signals.inc @@ -15,6 +15,7 @@ #include "Unix.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Mutex.h" +#include <string> #include <vector> #include <algorithm> #if HAVE_EXECINFO_H @@ -43,7 +44,7 @@ static SmartMutex<true> SignalsMutex; /// InterruptFunction - The function to call if ctrl-c is pressed. static void (*InterruptFunction)() = 0; -static std::vector<sys::Path> FilesToRemove; +static std::vector<std::string> FilesToRemove; static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun; // IntSigs - Signals that may interrupt the program at any time. @@ -117,10 +118,20 @@ static void UnregisterHandlers() { /// RemoveFilesToRemove - Process the FilesToRemove list. This function /// should be called with the SignalsMutex lock held. +/// NB: This must be an async signal safe function. It cannot allocate or free +/// memory, even in debug builds. static void RemoveFilesToRemove() { - while (!FilesToRemove.empty()) { - FilesToRemove.back().eraseFromDisk(true); - FilesToRemove.pop_back(); + // Note: avoid iterators in case of debug iterators that allocate or release + // memory. + for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) { + // Note that we don't want to use any external code here, and we don't care + // about errors. We're going to try as hard as we can as often as we need + // to to make these files go away. If these aren't files, too bad. + // + // We do however rely on a std::string implementation for which repeated + // calls to 'c_str()' don't allocate memory. We pre-call 'c_str()' on all + // of these strings to try to ensure this is safe. + unlink(FilesToRemove[i].c_str()); } } @@ -178,7 +189,19 @@ void llvm::sys::SetInterruptFunction(void (*IF)()) { bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename, std::string* ErrMsg) { SignalsMutex.acquire(); - FilesToRemove.push_back(Filename); + std::string *OldPtr = FilesToRemove.empty() ? 0 : &FilesToRemove[0]; + FilesToRemove.push_back(Filename.str()); + + // We want to call 'c_str()' on every std::string in this vector so that if + // the underlying implementation requires a re-allocation, it happens here + // rather than inside of the signal handler. If we see the vector grow, we + // have to call it on every entry. If it remains in place, we only need to + // call it on the latest one. + if (OldPtr == &FilesToRemove[0]) + FilesToRemove.back().c_str(); + else + for (unsigned i = 0, e = FilesToRemove.size(); i != e; ++i) + FilesToRemove[i].c_str(); SignalsMutex.release(); @@ -189,10 +212,19 @@ bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename, // DontRemoveFileOnSignal - The public API void llvm::sys::DontRemoveFileOnSignal(const sys::Path &Filename) { SignalsMutex.acquire(); - std::vector<sys::Path>::reverse_iterator I = - std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename); - if (I != FilesToRemove.rend()) - FilesToRemove.erase(I.base()-1); + std::vector<std::string>::reverse_iterator RI = + std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename.str()); + std::vector<std::string>::iterator I = FilesToRemove.end(); + if (RI != FilesToRemove.rend()) + I = FilesToRemove.erase(RI.base()-1); + + // We need to call c_str() on every element which would have been moved by + // the erase. These elements, in a C++98 implementation where c_str() + // requires a reallocation on the first call may have had the call to c_str() + // made on insertion become invalid by being copied down an element. + for (std::vector<std::string>::iterator E = FilesToRemove.end(); I != E; ++I) + I->c_str(); + SignalsMutex.release(); } diff --git a/lib/Support/Unix/Unix.h b/lib/Support/Unix/Unix.h index b7be311..361f297 100644 --- a/lib/Support/Unix/Unix.h +++ b/lib/Support/Unix/Unix.h @@ -44,16 +44,10 @@ #include <assert.h> #endif -#ifdef TIME_WITH_SYS_TIME +#ifdef HAVE_SYS_TIME_H # include <sys/time.h> -# include <time.h> -#else -# ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -# else -# include <time.h> -# endif #endif +#include <time.h> #ifdef HAVE_SYS_WAIT_H # include <sys/wait.h> |