]> git.ipfire.org Git - thirdparty/git.git/blobdiff - compat/mingw.c
Merge branch 'ep/maint-equals-null-cocci' for maint-2.35
[thirdparty/git.git] / compat / mingw.c
index e14f2d5f77ce7c5f7790f6f1f9143cc3fdae67b0..3b8adf8ed5d449d7a5b709f601e47e35dbf4df51 100644 (file)
@@ -1,5 +1,6 @@
 #include "../git-compat-util.h"
 #include "win32.h"
+#include <aclapi.h>
 #include <conio.h>
 #include <wchar.h>
 #include "../strbuf.h"
@@ -8,6 +9,8 @@
 #include "win32/lazyload.h"
 #include "../config.h"
 #include "dir.h"
+#define SECURITY_WIN32
+#include <sspi.h>
 
 #define HCAST(type, handle) ((type)(intptr_t)handle)
 
@@ -1008,7 +1011,7 @@ size_t mingw_strftime(char *s, size_t max,
        /* a pointer to the original strftime in case we can't find the UCRT version */
        static size_t (*fallback)(char *, size_t, const char *, const struct tm *) = strftime;
        size_t ret;
-       DECLARE_PROC_ADDR(ucrtbase.dll, size_t, strftime, char *, size_t,
+       DECLARE_PROC_ADDR(ucrtbase.dll, size_t, __cdecl, strftime, char *, size_t,
                const char *, const struct tm *);
 
        if (INIT_PROC_ADDR(strftime))
@@ -1042,7 +1045,7 @@ char *mingw_mktemp(char *template)
 int mkstemp(char *template)
 {
        char *filename = mktemp(template);
-       if (filename == NULL)
+       if (!filename)
                return -1;
        return open(filename, O_RDWR | O_CREAT, 0600);
 }
@@ -1125,6 +1128,10 @@ char *mingw_getcwd(char *pointer, int len)
        }
        if (!ret || ret >= ARRAY_SIZE(wpointer))
                return NULL;
+       if (GetFileAttributesW(wpointer) == INVALID_FILE_ATTRIBUTES) {
+               errno = ENOENT;
+               return NULL;
+       }
        if (xwcstoutf(pointer, wpointer, len) < 0)
                return NULL;
        convert_slashes(pointer);
@@ -2185,7 +2192,7 @@ enum EXTENDED_NAME_FORMAT {
 
 static char *get_extended_user_info(enum EXTENDED_NAME_FORMAT type)
 {
-       DECLARE_PROC_ADDR(secur32.dll, BOOL, GetUserNameExW,
+       DECLARE_PROC_ADDR(secur32.dll, BOOL, SEC_ENTRY, GetUserNameExW,
                enum EXTENDED_NAME_FORMAT, LPCWSTR, PULONG);
        static wchar_t wbuffer[1024];
        DWORD len;
@@ -2310,7 +2317,7 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out)
        static const struct timeval zero;
        static int atexit_done;
 
-       if (out != NULL)
+       if (out)
                return errno = EINVAL,
                        error("setitimer param 3 != NULL not implemented");
        if (!is_timeval_eq(&in->it_interval, &zero) &&
@@ -2339,7 +2346,7 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out)
        if (sig != SIGALRM)
                return errno = EINVAL,
                        error("sigaction only implemented for SIGALRM");
-       if (out != NULL)
+       if (out)
                return errno = EINVAL,
                        error("sigaction: param 3 != NULL not implemented");
 
@@ -2624,6 +2631,92 @@ static void setup_windows_environment(void)
        }
 }
 
+static PSID get_current_user_sid(void)
+{
+       HANDLE token;
+       DWORD len = 0;
+       PSID result = NULL;
+
+       if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
+               return NULL;
+
+       if (!GetTokenInformation(token, TokenUser, NULL, 0, &len)) {
+               TOKEN_USER *info = xmalloc((size_t)len);
+               if (GetTokenInformation(token, TokenUser, info, len, &len)) {
+                       len = GetLengthSid(info->User.Sid);
+                       result = xmalloc(len);
+                       if (!CopySid(len, result, info->User.Sid)) {
+                               error(_("failed to copy SID (%ld)"),
+                                     GetLastError());
+                               FREE_AND_NULL(result);
+                       }
+               }
+               FREE_AND_NULL(info);
+       }
+       CloseHandle(token);
+
+       return result;
+}
+
+int is_path_owned_by_current_sid(const char *path)
+{
+       WCHAR wpath[MAX_PATH];
+       PSID sid = NULL;
+       PSECURITY_DESCRIPTOR descriptor = NULL;
+       DWORD err;
+
+       static wchar_t home[MAX_PATH];
+
+       int result = 0;
+
+       if (xutftowcs_path(wpath, path) < 0)
+               return 0;
+
+       /*
+        * On Windows, the home directory is owned by the administrator, but for
+        * all practical purposes, it belongs to the user. Do pretend that it is
+        * owned by the user.
+        */
+       if (!*home) {
+               DWORD size = ARRAY_SIZE(home);
+               DWORD len = GetEnvironmentVariableW(L"HOME", home, size);
+               if (!len || len > size)
+                       wcscpy(home, L"::N/A::");
+       }
+       if (!wcsicmp(wpath, home))
+               return 1;
+
+       /* Get the owner SID */
+       err = GetNamedSecurityInfoW(wpath, SE_FILE_OBJECT,
+                                   OWNER_SECURITY_INFORMATION |
+                                   DACL_SECURITY_INFORMATION,
+                                   &sid, NULL, NULL, NULL, &descriptor);
+
+       if (err != ERROR_SUCCESS)
+               error(_("failed to get owner for '%s' (%ld)"), path, err);
+       else if (sid && IsValidSid(sid)) {
+               /* Now, verify that the SID matches the current user's */
+               static PSID current_user_sid;
+
+               if (!current_user_sid)
+                       current_user_sid = get_current_user_sid();
+
+               if (current_user_sid &&
+                   IsValidSid(current_user_sid) &&
+                   EqualSid(sid, current_user_sid))
+                       result = 1;
+       }
+
+       /*
+        * We can release the security descriptor struct only now because `sid`
+        * actually points into this struct.
+        */
+       if (descriptor)
+               LocalFree(descriptor);
+
+       return result;
+}
+
 int is_valid_win32_path(const char *path, int allow_literal_nul)
 {
        const char *p = path;