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