 1c854745bd
			
		
	
	1c854745bd
	
	
	
		
			
			Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
		
			
				
	
	
		
			166 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "test-tool.h"
 | |
| #include "git-compat-util.h"
 | |
| 
 | |
| #if defined(GIT_WINDOWS_NATIVE)
 | |
| 
 | |
| 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 ((Buffer[0] < 'A') || (Buffer[0] > 'Z'))
 | |
| 		return error("Invalid drive letter '%c'", Buffer[0]);
 | |
| 
 | |
| 	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;
 | |
| 	HMODULE ntdll;
 | |
| 	DWORD(WINAPI *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);
 | |
| 
 | |
| 	ntdll = LoadLibrary("ntdll.dll");
 | |
| 	if (!ntdll)
 | |
| 		return error("Can't load ntdll.dll, wrong Windows version?");
 | |
| 
 | |
| 	NtSetSystemInformation =
 | |
| 		(DWORD(WINAPI *)(INT, PVOID, ULONG))GetProcAddress(ntdll, "NtSetSystemInformation");
 | |
| 	if (!NtSetSystemInformation)
 | |
| 		return error("Can't get function addresses, wrong Windows version?");
 | |
| 
 | |
| 	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);
 | |
| 
 | |
| 	FreeLibrary(ntdll);
 | |
| 
 | |
| 	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();
 | |
| }
 |