]> git.ipfire.org Git - thirdparty/git.git/blob - t/helper/test-drop-caches.c
test-drop-caches: use `has_dos_drive_prefix()`
[thirdparty/git.git] / t / helper / test-drop-caches.c
1 #include "git-compat-util.h"
2
3 #if defined(GIT_WINDOWS_NATIVE)
4
5 static int cmd_sync(void)
6 {
7 char Buffer[MAX_PATH];
8 DWORD dwRet;
9 char szVolumeAccessPath[] = "\\\\.\\XXXX:";
10 HANDLE hVolWrite;
11 int success = 0, dos_drive_prefix;
12
13 dwRet = GetCurrentDirectory(MAX_PATH, Buffer);
14 if ((0 == dwRet) || (dwRet > MAX_PATH))
15 return error("Error getting current directory");
16
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';
23
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
41 typedef enum _SYSTEM_INFORMATION_CLASS {
42 SystemMemoryListInformation = 80,
43 } SYSTEM_INFORMATION_CLASS;
44
45 typedef 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
55 static 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
83 static 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
127 static int cmd_sync(void)
128 {
129 return system("sync");
130 }
131
132 static int cmd_dropcaches(void)
133 {
134 return system("echo 3 | sudo tee /proc/sys/vm/drop_caches");
135 }
136
137 #elif defined(__APPLE__)
138
139 static int cmd_sync(void)
140 {
141 return system("sync");
142 }
143
144 static int cmd_dropcaches(void)
145 {
146 return system("sudo purge");
147 }
148
149 #else
150
151 static int cmd_sync(void)
152 {
153 return 0;
154 }
155
156 static int cmd_dropcaches(void)
157 {
158 return error("drop caches not implemented on this platform");
159 }
160
161 #endif
162
163 int cmd_main(int argc, const char **argv)
164 {
165 cmd_sync();
166 return cmd_dropcaches();
167 }