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