]>
Commit | Line | Data |
---|---|---|
1c854745 | 1 | #include "test-tool.h" |
14527b30 BP |
2 | #include "git-compat-util.h" |
3 | ||
4 | #if defined(GIT_WINDOWS_NATIVE) | |
447ed832 | 5 | #include "lazyload.h" |
4a9b2049 | 6 | #include <winnt.h> |
14527b30 BP |
7 | |
8 | static int cmd_sync(void) | |
9 | { | |
10 | char Buffer[MAX_PATH]; | |
11 | DWORD dwRet; | |
68440496 | 12 | char szVolumeAccessPath[] = "\\\\.\\XXXX:"; |
14527b30 | 13 | HANDLE hVolWrite; |
68440496 | 14 | int success = 0, dos_drive_prefix; |
14527b30 BP |
15 | |
16 | dwRet = GetCurrentDirectory(MAX_PATH, Buffer); | |
17 | if ((0 == dwRet) || (dwRet > MAX_PATH)) | |
18 | return error("Error getting current directory"); | |
19 | ||
68440496 JS |
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'; | |
14527b30 | 26 | |
14527b30 BP |
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; | |
4a9b2049 MA |
90 | DECLARE_PROC_ADDR(ntdll.dll, DWORD, NTAPI, NtSetSystemInformation, INT, PVOID, |
91 | ULONG); | |
14527b30 BP |
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 | ||
447ed832 BP |
103 | if (!INIT_PROC_ADDR(NtSetSystemInformation)) |
104 | return error("Could not find NtSetSystemInformation() function"); | |
14527b30 BP |
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 | ||
14527b30 BP |
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 | ||
126e3b3d | 158 | int cmd__drop_caches(int argc UNUSED, const char **argv UNUSED) |
14527b30 BP |
159 | { |
160 | cmd_sync(); | |
161 | return cmd_dropcaches(); | |
162 | } |