]> git.ipfire.org Git - thirdparty/git.git/blame - t/helper/test-drop-caches.c
test-drop-caches: use `has_dos_drive_prefix()`
[thirdparty/git.git] / t / helper / test-drop-caches.c
CommitLineData
14527b30
BP
1#include "git-compat-util.h"
2
3#if defined(GIT_WINDOWS_NATIVE)
4
5static int cmd_sync(void)
6{
7 char Buffer[MAX_PATH];
8 DWORD dwRet;
68440496 9 char szVolumeAccessPath[] = "\\\\.\\XXXX:";
14527b30 10 HANDLE hVolWrite;
68440496 11 int success = 0, dos_drive_prefix;
14527b30
BP
12
13 dwRet = GetCurrentDirectory(MAX_PATH, Buffer);
14 if ((0 == dwRet) || (dwRet > MAX_PATH))
15 return error("Error getting current directory");
16
68440496
JS
17 dos_drive_prefix = has_dos_drive_prefix(Buffer);
18 if (!dos_drive_prefix)
19 return error("'%s': invalid drive letter", Buffer);
20
21 memcpy(szVolumeAccessPath, Buffer, dos_drive_prefix);
22 szVolumeAccessPath[dos_drive_prefix] = '\0';
14527b30 23
14527b30
BP
24 hVolWrite = CreateFile(szVolumeAccessPath, GENERIC_READ | GENERIC_WRITE,
25 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
26 if (INVALID_HANDLE_VALUE == hVolWrite)
27 return error("Unable to open volume for writing, need admin access");
28
29 success = FlushFileBuffers(hVolWrite);
30 if (!success)
31 error("Unable to flush volume");
32
33 CloseHandle(hVolWrite);
34
35 return !success;
36}
37
38#define STATUS_SUCCESS (0x00000000L)
39#define STATUS_PRIVILEGE_NOT_HELD (0xC0000061L)
40
41typedef enum _SYSTEM_INFORMATION_CLASS {
42 SystemMemoryListInformation = 80,
43} SYSTEM_INFORMATION_CLASS;
44
45typedef enum _SYSTEM_MEMORY_LIST_COMMAND {
46 MemoryCaptureAccessedBits,
47 MemoryCaptureAndResetAccessedBits,
48 MemoryEmptyWorkingSets,
49 MemoryFlushModifiedList,
50 MemoryPurgeStandbyList,
51 MemoryPurgeLowPriorityStandbyList,
52 MemoryCommandMax
53} SYSTEM_MEMORY_LIST_COMMAND;
54
55static BOOL GetPrivilege(HANDLE TokenHandle, LPCSTR lpName, int flags)
56{
57 BOOL bResult;
58 DWORD dwBufferLength;
59 LUID luid;
60 TOKEN_PRIVILEGES tpPreviousState;
61 TOKEN_PRIVILEGES tpNewState;
62
63 dwBufferLength = 16;
64 bResult = LookupPrivilegeValueA(0, lpName, &luid);
65 if (bResult) {
66 tpNewState.PrivilegeCount = 1;
67 tpNewState.Privileges[0].Luid = luid;
68 tpNewState.Privileges[0].Attributes = 0;
69 bResult = AdjustTokenPrivileges(TokenHandle, 0, &tpNewState,
70 (DWORD)((LPBYTE)&(tpNewState.Privileges[1]) - (LPBYTE)&tpNewState),
71 &tpPreviousState, &dwBufferLength);
72 if (bResult) {
73 tpPreviousState.PrivilegeCount = 1;
74 tpPreviousState.Privileges[0].Luid = luid;
75 tpPreviousState.Privileges[0].Attributes = flags != 0 ? 2 : 0;
76 bResult = AdjustTokenPrivileges(TokenHandle, 0, &tpPreviousState,
77 dwBufferLength, 0, 0);
78 }
79 }
80 return bResult;
81}
82
83static int cmd_dropcaches(void)
84{
85 HANDLE hProcess = GetCurrentProcess();
86 HANDLE hToken;
87 HMODULE ntdll;
88 DWORD(WINAPI *NtSetSystemInformation)(INT, PVOID, ULONG);
89 SYSTEM_MEMORY_LIST_COMMAND command;
90 int status;
91
92 if (!OpenProcessToken(hProcess, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
93 return error("Can't open current process token");
94
95 if (!GetPrivilege(hToken, "SeProfileSingleProcessPrivilege", 1))
96 return error("Can't get SeProfileSingleProcessPrivilege");
97
98 CloseHandle(hToken);
99
100 ntdll = LoadLibrary("ntdll.dll");
101 if (!ntdll)
102 return error("Can't load ntdll.dll, wrong Windows version?");
103
104 NtSetSystemInformation =
105 (DWORD(WINAPI *)(INT, PVOID, ULONG))GetProcAddress(ntdll, "NtSetSystemInformation");
106 if (!NtSetSystemInformation)
107 return error("Can't get function addresses, wrong Windows version?");
108
109 command = MemoryPurgeStandbyList;
110 status = NtSetSystemInformation(
111 SystemMemoryListInformation,
112 &command,
113 sizeof(SYSTEM_MEMORY_LIST_COMMAND)
114 );
115 if (status == STATUS_PRIVILEGE_NOT_HELD)
116 error("Insufficient privileges to purge the standby list, need admin access");
117 else if (status != STATUS_SUCCESS)
118 error("Unable to execute the memory list command %d", status);
119
120 FreeLibrary(ntdll);
121
122 return status;
123}
124
125#elif defined(__linux__)
126
127static int cmd_sync(void)
128{
129 return system("sync");
130}
131
132static int cmd_dropcaches(void)
133{
134 return system("echo 3 | sudo tee /proc/sys/vm/drop_caches");
135}
136
137#elif defined(__APPLE__)
138
139static int cmd_sync(void)
140{
141 return system("sync");
142}
143
144static int cmd_dropcaches(void)
145{
146 return system("sudo purge");
147}
148
149#else
150
151static int cmd_sync(void)
152{
153 return 0;
154}
155
156static int cmd_dropcaches(void)
157{
158 return error("drop caches not implemented on this platform");
159}
160
161#endif
162
163int cmd_main(int argc, const char **argv)
164{
165 cmd_sync();
166 return cmd_dropcaches();
167}