You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
157 lines
3.7 KiB
157 lines
3.7 KiB
#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(); |
|
}
|
|
|