|  | #define DISABLE_SIGN_COMPARE_WARNINGS | 
|  |  | 
|  | #include "test-tool.h" | 
|  | #include "git-compat-util.h" | 
|  |  | 
|  | #if defined(GIT_WINDOWS_NATIVE) | 
|  | #include "lazyload.h" | 
|  | #include <winnt.h> | 
|  |  | 
|  | static int cmd_sync(void) | 
|  | { | 
|  | char Buffer[MAX_PATH]; | 
|  | DWORD dwRet; | 
|  | char szVolumeAccessPath[] = "\\\\.\\XXXX:"; | 
|  | HANDLE hVolWrite; | 
|  | int success = 0, dos_drive_prefix; | 
|  |  | 
|  | dwRet = GetCurrentDirectory(MAX_PATH, Buffer); | 
|  | if ((0 == dwRet) || (dwRet > MAX_PATH)) | 
|  | return error("Error getting current directory"); | 
|  |  | 
|  | dos_drive_prefix = has_dos_drive_prefix(Buffer); | 
|  | if (!dos_drive_prefix) | 
|  | return error("'%s': invalid drive letter", Buffer); | 
|  |  | 
|  | memcpy(szVolumeAccessPath, Buffer, dos_drive_prefix); | 
|  | szVolumeAccessPath[dos_drive_prefix] = '\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, NTAPI, 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 UNUSED, const char **argv UNUSED) | 
|  | { | 
|  | cmd_sync(); | 
|  | return cmd_dropcaches(); | 
|  | } |