tvl-depot/third_party/git/t/helper/test-drop-caches.c
Vincent Ambo f4609b896f merge(3p/git): Merge git subtree at v2.29.2
This also bumps the stable nixpkgs to 20.09 as of 2020-11-21, because
there is some breakage in the git build related to the netrc
credentials helper which someone has taken care of in nixpkgs.

The stable channel is not used for anything other than git, so this
should be fine.

Change-Id: I3575a19dab09e1e9556cf8231d717de9890484fb
2020-11-21 19:45:56 +01:00

160 lines
3.9 KiB
C

#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[] = "\\\\.\\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, 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();
}