11#include "../git-compat-util.h"
22#include "win32.h"
3+ #include <aclapi.h>
34#include <conio.h>
45#include <wchar.h>
56#include "../strbuf.h"
@@ -1062,6 +1063,7 @@ int pipe(int filedes[2])
10621063 return 0 ;
10631064}
10641065
1066+ #ifndef __MINGW64__
10651067struct tm * gmtime_r (const time_t * timep , struct tm * result )
10661068{
10671069 if (gmtime_s (result , timep ) == 0 )
@@ -1075,6 +1077,7 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
10751077 return result ;
10761078 return NULL ;
10771079}
1080+ #endif
10781081
10791082char * mingw_getcwd (char * pointer , int len )
10801083{
@@ -2601,6 +2604,92 @@ static void setup_windows_environment(void)
26012604 }
26022605}
26032606
2607+ static PSID get_current_user_sid (void )
2608+ {
2609+ HANDLE token ;
2610+ DWORD len = 0 ;
2611+ PSID result = NULL ;
2612+
2613+ if (!OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY , & token ))
2614+ return NULL ;
2615+
2616+ if (!GetTokenInformation (token , TokenUser , NULL , 0 , & len )) {
2617+ TOKEN_USER * info = xmalloc ((size_t )len );
2618+ if (GetTokenInformation (token , TokenUser , info , len , & len )) {
2619+ len = GetLengthSid (info -> User .Sid );
2620+ result = xmalloc (len );
2621+ if (!CopySid (len , result , info -> User .Sid )) {
2622+ error (_ ("failed to copy SID (%ld)" ),
2623+ GetLastError ());
2624+ FREE_AND_NULL (result );
2625+ }
2626+ }
2627+ FREE_AND_NULL (info );
2628+ }
2629+ CloseHandle (token );
2630+
2631+ return result ;
2632+ }
2633+
2634+ int is_path_owned_by_current_sid (const char * path )
2635+ {
2636+ WCHAR wpath [MAX_PATH ];
2637+ PSID sid = NULL ;
2638+ PSECURITY_DESCRIPTOR descriptor = NULL ;
2639+ DWORD err ;
2640+
2641+ static wchar_t home [MAX_PATH ];
2642+
2643+ int result = 0 ;
2644+
2645+ if (xutftowcs_path (wpath , path ) < 0 )
2646+ return 0 ;
2647+
2648+ /*
2649+ * On Windows, the home directory is owned by the administrator, but for
2650+ * all practical purposes, it belongs to the user. Do pretend that it is
2651+ * owned by the user.
2652+ */
2653+ if (!* home ) {
2654+ DWORD size = ARRAY_SIZE (home );
2655+ DWORD len = GetEnvironmentVariableW (L"HOME" , home , size );
2656+ if (!len || len > size )
2657+ wcscpy (home , L"::N/A::" );
2658+ }
2659+ if (!wcsicmp (wpath , home ))
2660+ return 1 ;
2661+
2662+ /* Get the owner SID */
2663+ err = GetNamedSecurityInfoW (wpath , SE_FILE_OBJECT ,
2664+ OWNER_SECURITY_INFORMATION |
2665+ DACL_SECURITY_INFORMATION ,
2666+ & sid , NULL , NULL , NULL , & descriptor );
2667+
2668+ if (err != ERROR_SUCCESS )
2669+ error (_ ("failed to get owner for '%s' (%ld)" ), path , err );
2670+ else if (sid && IsValidSid (sid )) {
2671+ /* Now, verify that the SID matches the current user's */
2672+ static PSID current_user_sid ;
2673+
2674+ if (!current_user_sid )
2675+ current_user_sid = get_current_user_sid ();
2676+
2677+ if (current_user_sid &&
2678+ IsValidSid (current_user_sid ) &&
2679+ EqualSid (sid , current_user_sid ))
2680+ result = 1 ;
2681+ }
2682+
2683+ /*
2684+ * We can release the security descriptor struct only now because `sid`
2685+ * actually points into this struct.
2686+ */
2687+ if (descriptor )
2688+ LocalFree (descriptor );
2689+
2690+ return result ;
2691+ }
2692+
26042693int is_valid_win32_path (const char * path , int allow_literal_nul )
26052694{
26062695 const char * p = path ;
0 commit comments