#include "test-tool.h" #include "git-compat-util.h" #if defined(GIT_WINDOWS_NATIVE) #include "lazyload.h" static int cmd_sync(void) { char Buffer[MAX_PATH]; DWORD dwRet; char szVolumeAccessPath[] = "\\\\.\\X:"; HANDLE hVolWrite; int success = 0; dwRet = GetCurrentDirectory(MAX_PATH, Buffer); if ((0 == dwRet) || (dwRet > MAX_PATH)) return error("Error getting current directory"); if (!has_dos_drive_prefix(Buffer)) return error("'%s': invalid drive letter", Buffer); szVolumeAccessPath[4] = Buffer[0]; hVolWrite = CreateFile(szVolumeAccessPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (INVALID_HANDLE_VALUE == hVolWrite) return error("Unable to open volume for writing, need admin access"); success = FlushFileBuffers(hVolWrite); if (!success) error("Unable to flush volume"); CloseHandle(hVolWrite); return !success; } #define STATUS_SUCCESS (0x00000000L) #define STATUS_PRIVILEGE_NOT_HELD (0xC0000061L) typedef enum _SYSTEM_INFORMATION_CLASS { SystemMemoryListInformation = 80, } SYSTEM_INFORMATION_CLASS; typedef enum _SYSTEM_MEMORY_LIST_COMMAND { MemoryCaptureAccessedBits, MemoryCaptureAndResetAccessedBits, MemoryEmptyWorkingSets, MemoryFlushModifiedList, MemoryPurgeStandbyList, MemoryPurgeLowPriorityStandbyList, MemoryCommandMax } SYSTEM_MEMORY_LIST_COMMAND; static BOOL GetPrivilege(HANDLE TokenHandle, LPCSTR lpName, int flags) { BOOL bResult; DWORD dwBufferLength; LUID luid; TOKEN_PRIVILEGES tpPreviousState; TOKEN_PRIVILEGES tpNewState; dwBufferLength = 16; bResult = LookupPrivilegeValueA(0, lpName, &luid); if (bResult) { tpNewState.PrivilegeCount = 1; tpNewState.Privileges[0].Luid = luid; tpNewState.Privileges[0].Attributes = 0; bResult = AdjustTokenPrivileges(TokenHandle, 0, &tpNewState, (DWORD)((LPBYTE)&(tpNewState.Privileges[1]) - (LPBYTE)&tpNewState), &tpPreviousState, &dwBufferLength); if (bResult) { tpPreviousState.PrivilegeCount = 1; tpPreviousState.Privileges[0].Luid = luid; tpPreviousState.Privileges[0].Attributes = flags != 0 ? 2 : 0; bResult = AdjustTokenPrivileges(TokenHandle, 0, &tpPreviousState, dwBufferLength, 0, 0); } } return bResult; } static int cmd_dropcaches(void) { HANDLE hProcess = GetCurrentProcess(); HANDLE hToken; DECLARE_PROC_ADDR(ntdll.dll, DWORD, NtSetSystemInformation, INT, PVOID, ULONG); SYSTEM_MEMORY_LIST_COMMAND command; int status; if (!OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken)) return error("Can't open current process token"); if (!GetPrivilege(hToken, "SeProfileSingleProcessPrivilege", 1)) return error("Can't get SeProfileSingleProcessPrivilege"); CloseHandle(hToken); if (!INIT_PROC_ADDR(NtSetSystemInformation)) return error("Could not find NtSetSystemInformation() function"); command = MemoryPurgeStandbyList; status = NtSetSystemInformation( SystemMemoryListInformation, &command, sizeof(SYSTEM_MEMORY_LIST_COMMAND) ); if (status == STATUS_PRIVILEGE_NOT_HELD) error("Insufficient privileges to purge the standby list, need admin access"); else if (status != STATUS_SUCCESS) error("Unable to execute the memory list command %d", status); return status; } #elif defined(__linux__) static int cmd_sync(void) { return system("sync"); } static int cmd_dropcaches(void) { return system("echo 3 | sudo tee /proc/sys/vm/drop_caches"); } #elif defined(__APPLE__) static int cmd_sync(void) { return system("sync"); } static int cmd_dropcaches(void) { return system("sudo purge"); } #else static int cmd_sync(void) { return 0; } static int cmd_dropcaches(void) { return error("drop caches not implemented on this platform"); } #endif int cmd__drop_caches(int argc, const char **argv) { cmd_sync(); return cmd_dropcaches(); }