diff --git a/src/fileops.c b/src/fileops.c index 6dd9270b5..cd4b3c42a 100644 --- a/src/fileops.c +++ b/src/fileops.c @@ -354,110 +354,22 @@ int git_futils_rmdir_r(const char *path, git_directory_removal_type removal_type } #ifdef GIT_WIN32 -static char *win32_getenv(const wchar_t *name) -{ - char *val_utf8; - wchar_t *val_utf16; - DWORD len = GetEnvironmentVariableW(name, NULL, 0); - - if (len <= 0) - return NULL; - - val_utf16 = git__calloc(len, sizeof(wchar_t)); - if (!val_utf16) - return NULL; - - if (GetEnvironmentVariableW(name, val_utf16, len) != len - 1) { - giterr_set(GITERR_OS, "Could not read environment variable"); - git__free(val_utf16); - return NULL; - } - - val_utf8 = gitwin_from_utf16(val_utf16); - - git__free(val_utf16); - - return val_utf8; -} -#endif - -int git_futils_find_global_file(git_buf *path, const char *filename) -{ - char *home; - -#ifdef GIT_WIN32 - home = win32_getenv(L"HOME"); - - if (!home) - home = win32_getenv(L"USERPROFILE"); - - if (home) - git_path_mkposix(home); -#else - home = getenv("HOME"); -#endif - - if (home == NULL) { - giterr_set(GITERR_OS, "Global file lookup failed. " - "Cannot locate the user's home directory"); - return -1; - } - - if (git_buf_joinpath(path, home, filename) < 0) - return -1; - -#ifdef GIT_WIN32 - git__free(home); -#endif - - if (git_path_exists(path->ptr) == false) { - git_buf_clear(path); - return GIT_ENOTFOUND; - } - - return 0; -} - -#ifdef GIT_WIN32 -typedef struct { - wchar_t *path; +struct win32_path { + wchar_t path[MAX_PATH]; DWORD len; -} win32_path; +}; -static const win32_path *win32_system_root(void) +static int win32_expand_path(struct win32_path *s_root, const wchar_t *templ) { - static win32_path s_root = { 0, 0 }; - - if (s_root.path == NULL) { - const wchar_t *root_tmpl = L"%PROGRAMFILES%\\Git\\etc\\"; - - s_root.len = ExpandEnvironmentStringsW(root_tmpl, NULL, 0); - if (s_root.len <= 0) { - giterr_set(GITERR_OS, "Failed to expand environment strings"); - return NULL; - } - - s_root.path = git__calloc(s_root.len, sizeof(wchar_t)); - if (s_root.path == NULL) - return NULL; - - if (ExpandEnvironmentStringsW(root_tmpl, s_root.path, s_root.len) != s_root.len) { - giterr_set(GITERR_OS, "Failed to expand environment strings"); - git__free(s_root.path); - s_root.path = NULL; - return NULL; - } - } - - return &s_root; + s_root->len = ExpandEnvironmentStringsW(templ, s_root->path, MAX_PATH); + return s_root->len ? 0 : -1; } -static int win32_find_system_file(git_buf *path, const char *filename) +static int win32_find_file(git_buf *path, const struct win32_path *root, const char *filename) { int error = 0; - const win32_path *root = win32_system_root(); size_t len; - wchar_t *file_utf16 = NULL, *scan; + wchar_t *file_utf16 = NULL; char *file_utf8 = NULL; if (!root || !filename || (len = strlen(filename)) == 0) @@ -479,10 +391,6 @@ static int win32_find_system_file(git_buf *path, const char *filename) goto cleanup; } - for (scan = file_utf16; *scan; scan++) - if (*scan == L'/') - *scan = L'\\'; - /* check access */ if (_waccess(file_utf16, F_OK) < 0) { error = GIT_ENOTFOUND; @@ -499,13 +407,24 @@ static int win32_find_system_file(git_buf *path, const char *filename) cleanup: git__free(file_utf16); - return error; } #endif int git_futils_find_system_file(git_buf *path, const char *filename) { +#ifdef GIT_WIN32 + struct win32_path root; + + if (win32_expand_path(&root, L"%PROGRAMFILES%\\Git\\etc\\") < 0 || + win32_find_file(path, &root, filename) < 0) { + giterr_set(GITERR_OS, "Cannot find the system's Program Files directory"); + return -1; + } + + return 0; + +#else if (git_buf_joinpath(path, "/etc", filename) < 0) return -1; @@ -513,10 +432,39 @@ int git_futils_find_system_file(git_buf *path, const char *filename) return 0; git_buf_clear(path); - -#ifdef GIT_WIN32 - return win32_find_system_file(path, filename); -#else return GIT_ENOTFOUND; #endif } + +int git_futils_find_global_file(git_buf *path, const char *filename) +{ +#ifdef GIT_WIN32 + struct win32_path root; + + if (win32_expand_path(&root, L"%USERPROFILE%\\") < 0 || + win32_find_file(path, &root, filename) < 0) { + giterr_set(GITERR_OS, "Failed to lookup the current user's Windows profile"); + return -1; + } + + return 0; +#else + const char *home = getenv("HOME"); + + if (home == NULL) { + giterr_set(GITERR_OS, "Global file lookup failed. " + "Cannot locate the user's home directory"); + return -1; + } + + if (git_buf_joinpath(path, home, filename) < 0) + return -1; + + if (git_path_exists(path->ptr) == false) { + git_buf_clear(path); + return GIT_ENOTFOUND; + } + + return 0; +#endif +} diff --git a/tests-clar/core/env.c b/tests-clar/core/env.c index abe7bf87c..0d58e560b 100644 --- a/tests-clar/core/env.c +++ b/tests-clar/core/env.c @@ -53,26 +53,24 @@ static int cl_setenv(const char *name, const char *value) #endif static char *env_home = NULL; -#ifdef GIT_WIN32 static char *env_userprofile = NULL; -#endif void test_core_env__initialize(void) { - env_home = cl_getenv("HOME"); #ifdef GIT_WIN32 env_userprofile = cl_getenv("USERPROFILE"); +#else + env_home = cl_getenv("HOME"); #endif } void test_core_env__cleanup(void) { - cl_setenv("HOME", env_home); #ifdef GIT_WIN32 cl_setenv("USERPROFILE", env_userprofile); - - git__free(env_home); git__free(env_userprofile); +#else + cl_setenv("HOME", env_home); #endif } @@ -102,32 +100,25 @@ void test_core_env__0(void) */ cl_git_pass(git_path_prettify(&path, *val, NULL)); - cl_git_pass(cl_setenv("HOME", path.ptr)); - - /* do a quick check that it was set correctly */ - check = cl_getenv("HOME"); - cl_assert_equal_s(path.ptr, check); #ifdef GIT_WIN32 - git__free(check); - cl_git_pass(cl_setenv("USERPROFILE", path.ptr)); /* do a quick check that it was set correctly */ check = cl_getenv("USERPROFILE"); cl_assert_equal_s(path.ptr, check); git__free(check); +#else + cl_git_pass(cl_setenv("HOME", path.ptr)); + + /* do a quick check that it was set correctly */ + check = cl_getenv("HOME"); + cl_assert_equal_s(path.ptr, check); #endif cl_git_pass(git_buf_puts(&path, "/testfile")); cl_git_mkfile(path.ptr, "find me"); cl_git_pass(git_futils_find_global_file(&found, "testfile")); - -#ifdef GIT_WIN32 - /* do another check with HOME unset */ - cl_git_pass(cl_setenv("HOME", NULL)); - cl_git_pass(git_futils_find_global_file(&found, "testfile")); -#endif } }