diff options
Diffstat (limited to 'compat/mingw.c')
| -rw-r--r-- | compat/mingw.c | 85 |
1 files changed, 71 insertions, 14 deletions
diff --git a/compat/mingw.c b/compat/mingw.c index 6fe80fdf01..d614f156df 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -1,6 +1,7 @@ #include "../git-compat-util.h" #include "win32.h" #include <aclapi.h> +#include <sddl.h> #include <conio.h> #include <wchar.h> #include "../strbuf.h" @@ -195,16 +196,19 @@ static int read_yes_no_answer(void) static int ask_yes_no_if_possible(const char *format, ...) { char question[4096]; - const char *retry_hook[] = { NULL, NULL, NULL }; + const char *retry_hook; va_list args; va_start(args, format); vsnprintf(question, sizeof(question), format, args); va_end(args); - if ((retry_hook[0] = mingw_getenv("GIT_ASK_YESNO"))) { - retry_hook[1] = question; - return !run_command_v_opt(retry_hook, 0); + retry_hook = mingw_getenv("GIT_ASK_YESNO"); + if (retry_hook) { + struct child_process cmd = CHILD_PROCESS_INIT; + + strvec_pushl(&cmd.args, retry_hook, question, NULL); + return !run_command(&cmd); } if (!isatty(_fileno(stdin)) || !isatty(_fileno(stderr))) @@ -768,8 +772,8 @@ static int has_valid_directory_prefix(wchar_t *wfilename) wfilename[n] = L'\0'; attributes = GetFileAttributesW(wfilename); wfilename[n] = c; - if (attributes == FILE_ATTRIBUTE_DIRECTORY || - attributes == FILE_ATTRIBUTE_DEVICE) + if (attributes & + (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE)) return 1; if (attributes == INVALID_FILE_ATTRIBUTES) switch (GetLastError()) { @@ -1059,10 +1063,7 @@ char *mingw_mktemp(char *template) int mkstemp(char *template) { - char *filename = mktemp(template); - if (filename == NULL) - return -1; - return open(filename, O_RDWR | O_CREAT, 0600); + return git_mkstemp_mode(template, 0600); } int gettimeofday(struct timeval *tv, void *tz) @@ -2332,7 +2333,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) && @@ -2361,7 +2362,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"); @@ -2673,7 +2674,22 @@ static PSID get_current_user_sid(void) return result; } -int is_path_owned_by_current_sid(const char *path) +static int acls_supported(const char *path) +{ + size_t offset = offset_1st_component(path); + WCHAR wroot[MAX_PATH]; + DWORD file_system_flags; + + if (offset && + xutftowcsn(wroot, path, MAX_PATH, offset) > 0 && + GetVolumeInformationW(wroot, NULL, 0, NULL, NULL, + &file_system_flags, NULL, 0)) + return !!(file_system_flags & FILE_PERSISTENT_ACLS); + + return 0; +} + +int is_path_owned_by_current_sid(const char *path, struct strbuf *report) { WCHAR wpath[MAX_PATH]; PSID sid = NULL; @@ -2712,6 +2728,7 @@ int is_path_owned_by_current_sid(const char *path) else if (sid && IsValidSid(sid)) { /* Now, verify that the SID matches the current user's */ static PSID current_user_sid; + BOOL is_member; if (!current_user_sid) current_user_sid = get_current_user_sid(); @@ -2720,6 +2737,46 @@ int is_path_owned_by_current_sid(const char *path) IsValidSid(current_user_sid) && EqualSid(sid, current_user_sid)) result = 1; + else if (IsWellKnownSid(sid, WinBuiltinAdministratorsSid) && + CheckTokenMembership(NULL, sid, &is_member) && + is_member) + /* + * If owned by the Administrators group, and the + * current user is an administrator, we consider that + * okay, too. + */ + result = 1; + else if (report && + IsWellKnownSid(sid, WinWorldSid) && + !acls_supported(path)) { + /* + * On FAT32 volumes, ownership is not actually recorded. + */ + strbuf_addf(report, "'%s' is on a file system that does" + "not record ownership\n", path); + } else if (report) { + LPSTR str1, str2, to_free1 = NULL, to_free2 = NULL; + + if (ConvertSidToStringSidA(sid, &str1)) + to_free1 = str1; + else + str1 = "(inconvertible)"; + + if (!current_user_sid) + str2 = "(none)"; + else if (!IsValidSid(current_user_sid)) + str2 = "(invalid)"; + else if (ConvertSidToStringSidA(current_user_sid, &str2)) + to_free2 = str2; + else + str2 = "(inconvertible)"; + strbuf_addf(report, + "'%s' is owned by:\n" + "\t'%s'\nbut the current user is:\n" + "\t'%s'\n", path, str1, str2); + LocalFree(to_free1); + LocalFree(to_free2); + } } /* @@ -2830,7 +2887,7 @@ not_a_reserved_name: } c = path[i]; - if (c && c != '.' && c != ':' && c != '/' && c != '\\') + if (c && c != '.' && c != ':' && !is_xplatform_dir_sep(c)) goto not_a_reserved_name; /* contains reserved name */ |
