From a132064b4821ee21c45717b459351ac4ffe4d372 Mon Sep 17 00:00:00 2001 From: KWSys Upstream Date: Mon, 22 Feb 2016 08:56:45 -0500 Subject: [PATCH] KWSys 2016-02-22 (4847aedd) Code extracted from: http://public.kitware.com/KWSys.git at commit 4847aedde22b0026accbb71e5480ed353a330e02 (master). Upstream Shortlog ----------------- Ben Boeckel (1): de83c4d4 SystemTools: support deleting junction points Chuck Atkins (1): 3e1b7395 SystemInformation: Ignore buffers and cache when reporting host memory use Costy Petrisor (1): 9fe15333 Update hidden includes to support CMake header dependency scanning Zack Galbreath (1): 4847aedd Process: Allow timeout to be changed after child starts --- CommandLineArguments.cxx | 1 + ProcessUNIX.c | 2 + ProcessWin32.c | 4 +- SystemInformation.cxx | 38 +++++++++----- SystemTools.cxx | 107 +++++++++++++++++++++++++++++++++++++++ testHashSTL.cxx | 1 - testIOS.cxx | 6 +++ 7 files changed, 143 insertions(+), 16 deletions(-) diff --git a/CommandLineArguments.cxx b/CommandLineArguments.cxx index 36368368b..f713294da 100644 --- a/CommandLineArguments.cxx +++ b/CommandLineArguments.cxx @@ -20,6 +20,7 @@ #if 0 # include "CommandLineArguments.hxx.in" # include "Configure.hxx.in" +# include "String.hxx.in" #endif #include diff --git a/ProcessUNIX.c b/ProcessUNIX.c index 07c644b8e..74029553b 100644 --- a/ProcessUNIX.c +++ b/ProcessUNIX.c @@ -505,6 +505,8 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) { cp->Timeout = 0; } + // Force recomputation of TimeoutTime. + cp->TimeoutTime.tv_sec = -1; } /*--------------------------------------------------------------------------*/ diff --git a/ProcessWin32.c b/ProcessWin32.c index 1f8749fbe..a18ea2748 100644 --- a/ProcessWin32.c +++ b/ProcessWin32.c @@ -17,7 +17,7 @@ duplicate the above list of headers. */ #if 0 # include "Process.h.in" -# include "Encoding_c.h.in" +# include "Encoding.h.in" #endif /* @@ -698,6 +698,8 @@ void kwsysProcess_SetTimeout(kwsysProcess* cp, double timeout) { cp->Timeout = 0; } + // Force recomputation of TimeoutTime. + cp->TimeoutTime.QuadPart = -1; } /*--------------------------------------------------------------------------*/ diff --git a/SystemInformation.cxx b/SystemInformation.cxx index cddcc8dcb..127a04822 100644 --- a/SystemInformation.cxx +++ b/SystemInformation.cxx @@ -43,7 +43,6 @@ #if 0 # include "SystemInformation.hxx.in" # include "Process.h.in" -# include "Configure.hxx.in" #endif #include @@ -3570,33 +3569,44 @@ SystemInformationImplementation::GetHostMemoryUsed() return (statex.ullTotalPhys - statex.ullAvailPhys)/1024; # endif #elif defined(__linux) - const char *names[3]={"MemTotal:","MemFree:",NULL}; - SystemInformation::LongLong values[2]={SystemInformation::LongLong(0)}; - int ierr=GetFieldsFromFile("/proc/meminfo",names,values); + // First try to use MemAvailable, but it only works on newer kernels + const char *names2[3]={"MemTotal:","MemAvailable:",NULL}; + SystemInformation::LongLong values2[2]={SystemInformation::LongLong(0)}; + int ierr=GetFieldsFromFile("/proc/meminfo",names2,values2); if (ierr) { - return ierr; + const char *names4[5]={"MemTotal:","MemFree:","Buffers:","Cached:",NULL}; + SystemInformation::LongLong values4[4]={SystemInformation::LongLong(0)}; + ierr=GetFieldsFromFile("/proc/meminfo",names4,values4); + if(ierr) + { + return ierr; + } + SystemInformation::LongLong &memTotal=values4[0]; + SystemInformation::LongLong &memFree=values4[1]; + SystemInformation::LongLong &memBuffers=values4[2]; + SystemInformation::LongLong &memCached=values4[3]; + return memTotal - memFree - memBuffers - memCached; } - SystemInformation::LongLong &memTotal=values[0]; - SystemInformation::LongLong &memFree=values[1]; - return memTotal - memFree; + SystemInformation::LongLong &memTotal=values2[0]; + SystemInformation::LongLong &memAvail=values2[1]; + return memTotal - memAvail; #elif defined(__APPLE__) SystemInformation::LongLong psz=getpagesize(); if (psz<1) { return -1; } - const char *names[4]={"Pages active:","Pages inactive:","Pages wired down:",NULL}; - SystemInformation::LongLong values[3]={SystemInformation::LongLong(0)}; + const char *names[3]={"Pages wired down:","Pages active:",NULL}; + SystemInformation::LongLong values[2]={SystemInformation::LongLong(0)}; int ierr=GetFieldsFromCommand("vm_stat", names, values); if (ierr) { return -1; } - SystemInformation::LongLong &vmActive=values[0]; - SystemInformation::LongLong &vmInactive=values[1]; - SystemInformation::LongLong &vmWired=values[2]; - return ((vmActive+vmInactive+vmWired)*psz)/1024; + SystemInformation::LongLong &vmWired=values[0]; + SystemInformation::LongLong &vmActive=values[1]; + return ((vmActive+vmWired)*psz)/1024; #else return 0; #endif diff --git a/SystemTools.cxx b/SystemTools.cxx index e3428f878..544a638ca 100644 --- a/SystemTools.cxx +++ b/SystemTools.cxx @@ -35,10 +35,12 @@ #include #include #include +#include // Work-around CMake dependency scanning limitation. This must // duplicate the above list of headers. #if 0 +# include "RegularExpression.hxx.in" # include "SystemTools.hxx.in" # include "Directory.hxx.in" # include "FStream.hxx.in" @@ -87,6 +89,7 @@ // Windows API. #if defined(_WIN32) # include +# include # ifndef INVALID_FILE_ATTRIBUTES # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) # endif @@ -2754,6 +2757,106 @@ std::string SystemTools::GetLastSystemError() return strerror(e); } +#ifdef _WIN32 + +static bool IsJunction(const std::wstring& source) +{ +#ifdef FSCTL_GET_REPARSE_POINT + const DWORD JUNCTION_ATTRS = FILE_ATTRIBUTE_DIRECTORY | + FILE_ATTRIBUTE_REPARSE_POINT; + DWORD attrs = GetFileAttributesW(source.c_str()); + if (attrs == INVALID_FILE_ATTRIBUTES) + { + return false; + } + if ((attrs & JUNCTION_ATTRS) != JUNCTION_ATTRS) + { + return false; + } + + // Adjust privileges so that we can succefully open junction points. + HANDLE token; + TOKEN_PRIVILEGES privs; + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token); + LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &privs.Privileges[0].Luid); + privs.PrivilegeCount = 1; + privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(token, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + CloseHandle(token); + + HANDLE dir = CreateFileW(source.c_str(), GENERIC_READ, + 0, NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (dir == INVALID_HANDLE_VALUE) + { + return false; + } + + // Query whether this is a reparse point or not. + BYTE buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + REPARSE_GUID_DATA_BUFFER *reparse_buffer = + (REPARSE_GUID_DATA_BUFFER*) buffer; + DWORD sentinel; + + BOOL success = DeviceIoControl( + dir, FSCTL_GET_REPARSE_POINT, + NULL, 0, + reparse_buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, + &sentinel, NULL); + + CloseHandle(dir); + + return (success && (reparse_buffer->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT)); +#else + return false; +#endif +} + +static bool DeleteJunction(const std::wstring& source) +{ +#ifdef FSCTL_DELETE_REPARSE_POINT + // Adjust privileges so that we can succefully open junction points as + // read/write. + HANDLE token; + TOKEN_PRIVILEGES privs; + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token); + LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &privs.Privileges[0].Luid); + privs.PrivilegeCount = 1; + privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + AdjustTokenPrivileges(token, FALSE, &privs, sizeof(TOKEN_PRIVILEGES), NULL, NULL); + CloseHandle(token); + + HANDLE dir = CreateFileW(source.c_str(), GENERIC_READ | GENERIC_WRITE, + 0, NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (dir == INVALID_HANDLE_VALUE) + { + return false; + } + + // Set up the structure so that we can delete the junction. + std::vector buffer(REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, 0); + REPARSE_GUID_DATA_BUFFER *reparse_buffer = + (REPARSE_GUID_DATA_BUFFER*) &buffer[0]; + DWORD sentinel; + + reparse_buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT; + + BOOL success = DeviceIoControl( + dir, FSCTL_DELETE_REPARSE_POINT, + reparse_buffer, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, + NULL, 0, + &sentinel, NULL); + + CloseHandle(dir); + + return !!success; +#else + return false; +#endif +} +#endif + bool SystemTools::RemoveFile(const std::string& source) { #ifdef _WIN32 @@ -2781,6 +2884,10 @@ bool SystemTools::RemoveFile(const std::string& source) SetLastError(err); return false; } + if (IsJunction(ws) && !DeleteJunction(ws)) + { + return false; + } if (DeleteFileW(ws.c_str()) || GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND) diff --git a/testHashSTL.cxx b/testHashSTL.cxx index ab1f83e78..ae66cebea 100644 --- a/testHashSTL.cxx +++ b/testHashSTL.cxx @@ -18,7 +18,6 @@ #if 0 # include "hash_map.hxx.in" # include "hash_set.hxx.in" -# include "hashtable.hxx.in" #endif #include diff --git a/testIOS.cxx b/testIOS.cxx index 396a09d47..5ff7955bf 100644 --- a/testIOS.cxx +++ b/testIOS.cxx @@ -18,6 +18,12 @@ #include #include /* strlen */ +// Work-around CMake dependency scanning limitation. This must +// duplicate the above list of headers. +#if 0 +# include "Configure.hxx.in" +#endif + int testIOS(int, char*[]) { std::ostringstream ostr;