1 #include "git-compat-util.h"
3 #if defined(GIT_WINDOWS_NATIVE)
5 static int cmd_sync(void)
9 char szVolumeAccessPath
[] = "\\\\.\\XXXX:";
11 int success
= 0, dos_drive_prefix
;
13 dwRet
= GetCurrentDirectory(MAX_PATH
, Buffer
);
14 if ((0 == dwRet
) || (dwRet
> MAX_PATH
))
15 return error("Error getting current directory");
17 dos_drive_prefix
= has_dos_drive_prefix(Buffer
);
18 if (!dos_drive_prefix
)
19 return error("'%s': invalid drive letter", Buffer
);
21 memcpy(szVolumeAccessPath
, Buffer
, dos_drive_prefix
);
22 szVolumeAccessPath
[dos_drive_prefix
] = '\0';
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");
29 success
= FlushFileBuffers(hVolWrite
);
31 error("Unable to flush volume");
33 CloseHandle(hVolWrite
);
38 #define STATUS_SUCCESS (0x00000000L)
39 #define STATUS_PRIVILEGE_NOT_HELD (0xC0000061L)
41 typedef enum _SYSTEM_INFORMATION_CLASS
{
42 SystemMemoryListInformation
= 80,
43 } SYSTEM_INFORMATION_CLASS
;
45 typedef enum _SYSTEM_MEMORY_LIST_COMMAND
{
46 MemoryCaptureAccessedBits
,
47 MemoryCaptureAndResetAccessedBits
,
48 MemoryEmptyWorkingSets
,
49 MemoryFlushModifiedList
,
50 MemoryPurgeStandbyList
,
51 MemoryPurgeLowPriorityStandbyList
,
53 } SYSTEM_MEMORY_LIST_COMMAND
;
55 static BOOL
GetPrivilege(HANDLE TokenHandle
, LPCSTR lpName
, int flags
)
60 TOKEN_PRIVILEGES tpPreviousState
;
61 TOKEN_PRIVILEGES tpNewState
;
64 bResult
= LookupPrivilegeValueA(0, lpName
, &luid
);
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
);
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);
83 static int cmd_dropcaches(void)
85 HANDLE hProcess
= GetCurrentProcess();
88 DWORD(WINAPI
*NtSetSystemInformation
)(INT
, PVOID
, ULONG
);
89 SYSTEM_MEMORY_LIST_COMMAND command
;
92 if (!OpenProcessToken(hProcess
, TOKEN_QUERY
| TOKEN_ADJUST_PRIVILEGES
, &hToken
))
93 return error("Can't open current process token");
95 if (!GetPrivilege(hToken
, "SeProfileSingleProcessPrivilege", 1))
96 return error("Can't get SeProfileSingleProcessPrivilege");
100 ntdll
= LoadLibrary("ntdll.dll");
102 return error("Can't load ntdll.dll, wrong Windows version?");
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?");
109 command
= MemoryPurgeStandbyList
;
110 status
= NtSetSystemInformation(
111 SystemMemoryListInformation
,
113 sizeof(SYSTEM_MEMORY_LIST_COMMAND
)
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
);
125 #elif defined(__linux__)
127 static int cmd_sync(void)
129 return system("sync");
132 static int cmd_dropcaches(void)
134 return system("echo 3 | sudo tee /proc/sys/vm/drop_caches");
137 #elif defined(__APPLE__)
139 static int cmd_sync(void)
141 return system("sync");
144 static int cmd_dropcaches(void)
146 return system("sudo purge");
151 static int cmd_sync(void)
156 static int cmd_dropcaches(void)
158 return error("drop caches not implemented on this platform");
163 int cmd_main(int argc
, const char **argv
)
166 return cmd_dropcaches();