vendor/libgit2/src/win32/findfile.c in rugged-0.19.0 vs vendor/libgit2/src/win32/findfile.c in rugged-0.21.0

- old
+ new

@@ -15,58 +15,38 @@ #define REG_MSYSGIT_INSTALL REG_MSYSGIT_INSTALL_LOCAL #else #define REG_MSYSGIT_INSTALL L"SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Git_is1" #endif -int git_win32__expand_path(struct git_win32__path *s_root, const wchar_t *templ) -{ - s_root->len = ExpandEnvironmentStringsW(templ, s_root->path, MAX_PATH); - return s_root->len ? 0 : -1; -} +typedef struct { + git_win32_path path; + DWORD len; +} _findfile_path; -static int win32_path_utf16_to_8(git_buf *path_utf8, const wchar_t *path_utf16) +static int git_win32__expand_path(_findfile_path *dest, const wchar_t *src) { - char temp_utf8[GIT_PATH_MAX]; + dest->len = ExpandEnvironmentStringsW(src, dest->path, ARRAY_SIZE(dest->path)); - git__utf16_to_8(temp_utf8, path_utf16); - git_path_mkposix(temp_utf8); + if (!dest->len || dest->len > ARRAY_SIZE(dest->path)) + return -1; - return git_buf_sets(path_utf8, temp_utf8); + return 0; } -int git_win32__find_file( - git_buf *path, const struct git_win32__path *root, const char *filename) +static int win32_path_to_8(git_buf *dest, const wchar_t *src) { - size_t len, alloc_len; - wchar_t *file_utf16 = NULL; + git_win32_utf8_path utf8_path; - if (!root || !filename || (len = strlen(filename)) == 0) - return GIT_ENOTFOUND; - - /* allocate space for wchar_t path to file */ - alloc_len = root->len + len + 2; - file_utf16 = git__calloc(alloc_len, sizeof(wchar_t)); - GITERR_CHECK_ALLOC(file_utf16); - - /* append root + '\\' + filename as wchar_t */ - memcpy(file_utf16, root->path, root->len * sizeof(wchar_t)); - - if (*filename == '/' || *filename == '\\') - filename++; - - git__utf8_to_16(file_utf16 + root->len - 1, alloc_len, filename); - - /* check access */ - if (_waccess(file_utf16, F_OK) < 0) { - git__free(file_utf16); - return GIT_ENOTFOUND; + if (git_win32_path_to_utf8(utf8_path, src) < 0) { + giterr_set(GITERR_OS, "Unable to convert path to UTF-8"); + return -1; } - win32_path_utf16_to_8(path, file_utf16); - git__free(file_utf16); + /* Convert backslashes to forward slashes */ + git_path_mkposix(utf8_path); - return 0; + return git_buf_sets(dest, utf8_path); } static wchar_t* win32_walkpath(wchar_t *path, wchar_t *buf, size_t buflen) { wchar_t term, *base = path; @@ -84,14 +64,14 @@ path++; return (path != base) ? path : NULL; } -static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe) +static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe, const wchar_t *subdir) { wchar_t *env = _wgetenv(L"PATH"), lastch; - struct git_win32__path root; + _findfile_path root; size_t gitexe_len = wcslen(gitexe); if (!env) return -1; @@ -108,69 +88,70 @@ if (root.len + gitexe_len >= MAX_PATH) continue; wcscpy(&root.path[root.len], gitexe); if (_waccess(root.path, F_OK) == 0 && root.len > 5) { - /* replace "bin\\" or "cmd\\" with "etc\\" */ - wcscpy(&root.path[root.len - 4], L"etc\\"); + /* replace "bin\\" or "cmd\\" with subdir */ + wcscpy(&root.path[root.len - 4], subdir); - win32_path_utf16_to_8(buf, root.path); + win32_path_to_8(buf, root.path); return 0; } } return GIT_ENOTFOUND; } static int win32_find_git_in_registry( - git_buf *buf, const HKEY hieve, const wchar_t *key) + git_buf *buf, const HKEY hive, const wchar_t *key, const wchar_t *subdir) { HKEY hKey; - DWORD dwType = REG_SZ; - struct git_win32__path path16; + int error = GIT_ENOTFOUND; assert(buf); - path16.len = 0; + if (!RegOpenKeyExW(hive, key, 0, KEY_READ, &hKey)) { + DWORD dwType, cbData; + git_win32_path path; - if (RegOpenKeyExW(hieve, key, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) { - if (RegQueryValueExW(hKey, L"InstallLocation", NULL, &dwType, - (LPBYTE)&path16.path, &path16.len) == ERROR_SUCCESS) - { - /* InstallLocation points to the root of the git directory */ + /* Ensure that the buffer is big enough to have the suffix attached + * after we receive the result. */ + cbData = (DWORD)(sizeof(path) - wcslen(subdir) * sizeof(wchar_t)); - if (path16.len + 4 > MAX_PATH) { /* 4 = wcslen(L"etc\\") */ - giterr_set(GITERR_OS, "Cannot locate git - path too long"); - return -1; - } + /* InstallLocation points to the root of the git directory */ + if (!RegQueryValueExW(hKey, L"InstallLocation", NULL, &dwType, (LPBYTE)path, &cbData) && + dwType == REG_SZ) { - wcscat(path16.path, L"etc\\"); - path16.len += 4; + /* Append the suffix */ + wcscat(path, subdir); - win32_path_utf16_to_8(buf, path16.path); + /* Convert to UTF-8, with forward slashes, and output the path + * to the provided buffer */ + if (!win32_path_to_8(buf, path)) + error = 0; } RegCloseKey(hKey); } - return path16.len ? 0 : GIT_ENOTFOUND; + return error; } static int win32_find_existing_dirs( git_buf *out, const wchar_t *tmpl[]) { - struct git_win32__path path16; + _findfile_path path16; git_buf buf = GIT_BUF_INIT; git_buf_clear(out); for (; *tmpl != NULL; tmpl++) { if (!git_win32__expand_path(&path16, *tmpl) && path16.path[0] != L'%' && !_waccess(path16.path, F_OK)) { - win32_path_utf16_to_8(&buf, path16.path); + win32_path_to_8(&buf, path16.path); if (buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); } } @@ -178,29 +159,29 @@ git_buf_free(&buf); return (git_buf_oom(out) ? -1 : 0); } -int git_win32__find_system_dirs(git_buf *out) +int git_win32__find_system_dirs(git_buf *out, const wchar_t *subdir) { git_buf buf = GIT_BUF_INIT; /* directories where git.exe & git.cmd are found */ - if (!win32_find_git_in_path(&buf, L"git.exe") && buf.size) + if (!win32_find_git_in_path(&buf, L"git.exe", subdir) && buf.size) git_buf_set(out, buf.ptr, buf.size); else git_buf_clear(out); - if (!win32_find_git_in_path(&buf, L"git.cmd") && buf.size) + if (!win32_find_git_in_path(&buf, L"git.cmd", subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); /* directories where git is installed according to registry */ if (!win32_find_git_in_registry( - &buf, HKEY_CURRENT_USER, REG_MSYSGIT_INSTALL_LOCAL) && buf.size) + &buf, HKEY_CURRENT_USER, REG_MSYSGIT_INSTALL_LOCAL, subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); if (!win32_find_git_in_registry( - &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL) && buf.size) + &buf, HKEY_LOCAL_MACHINE, REG_MSYSGIT_INSTALL, subdir) && buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); git_buf_free(&buf); return (git_buf_oom(out) ? -1 : 0);