int win32_find_file(git_buf *path, const struct win32_path *root, const char *filename) { size_t len, alloc_len; wchar_t *file_utf16 = NULL; char file_utf8[GIT_PATH_MAX]; 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; } git__utf16_to_8(file_utf8, file_utf16); git_path_mkposix(file_utf8); git_buf_sets(path, file_utf8); git__free(file_utf16); return 0; }
int git_win32_path_to_utf8(git_win32_utf8_path dest, const wchar_t *src) { char *out = dest; int len; /* Strip NT namespacing "\\?\" */ if (path__is_nt_namespace(src)) { src += 4; /* "\\?\UNC\server\share" -> "\\server\share" */ if (wcsncmp(src, L"UNC\\", 4) == 0) { src += 4; memcpy(dest, "\\\\", 2); out = dest + 2; } } if ((len = git__utf16_to_8(out, GIT_WIN_PATH_UTF8, src)) < 0) return len; git_path_mkposix(dest); return len; }
char *p_realpath(const char *orig_path, char *buffer) { int ret; wchar_t* orig_path_w = gitwin_to_utf16(orig_path); wchar_t* buffer_w = (wchar_t*)git__malloc(GIT_PATH_MAX * sizeof(wchar_t)); ret = GetFullPathNameW(orig_path_w, GIT_PATH_MAX, buffer_w, NULL); git__free(orig_path_w); if (!ret || ret > GIT_PATH_MAX) { buffer = NULL; goto done; } if (buffer == NULL) { int buffer_sz = WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, NULL, 0, NULL, NULL); if (!buffer_sz || !(buffer = (char *)git__malloc(buffer_sz)) || !WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, buffer, buffer_sz, NULL, NULL)) { git__free(buffer); buffer = NULL; } } else { if (!WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, buffer, GIT_PATH_MAX, NULL, NULL)) buffer = NULL; } done: git__free(buffer_w); if (buffer) git_path_mkposix(buffer); return buffer; }
/* * Read the contents of `file_path` and set `path_out` to the repo dir that * it points to. Before calling, set `path_out` to the base directory that * should be used if the contents of `file_path` are a relative path. */ static int read_gitfile(git_buf *path_out, const char *file_path) { int error = 0; git_buf file = GIT_BUF_INIT; size_t prefix_len = strlen(GIT_FILE_CONTENT_PREFIX); assert(path_out && file_path); if (git_futils_readbuffer(&file, file_path) < 0) return -1; git_buf_rtrim(&file); /* apparently on Windows, some people use backslashes in paths */ git_path_mkposix(file.ptr); if (git_buf_len(&file) <= prefix_len || memcmp(git_buf_cstr(&file), GIT_FILE_CONTENT_PREFIX, prefix_len) != 0) { giterr_set(GITERR_REPOSITORY, "The `.git` file at '%s' is malformed", file_path); error = -1; } else if ((error = git_path_dirname_r(path_out, file_path)) >= 0) { const char *gitlink = git_buf_cstr(&file) + prefix_len; while (*gitlink && git__isspace(*gitlink)) gitlink++; error = git_path_prettify_dir( path_out, gitlink, git_buf_cstr(path_out)); } git_buf_free(&file); return error; }
static char *get_filename(const char *in) { #ifdef GIT_WIN32 HANDLE fh; HMODULE kerneldll; char *filename; typedef DWORD (__stdcall *getfinalpathname)(HANDLE, LPSTR, DWORD, DWORD); getfinalpathname getfinalpathfn; cl_assert(filename = malloc(MAX_PATH)); cl_assert(kerneldll = LoadLibrary("kernel32.dll")); cl_assert(getfinalpathfn = (getfinalpathname)GetProcAddress(kerneldll, "GetFinalPathNameByHandleA")); cl_assert(fh = CreateFileA(in, FILE_READ_ATTRIBUTES | STANDARD_RIGHTS_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)); cl_win32_pass(getfinalpathfn(fh, filename, MAX_PATH, VOLUME_NAME_DOS)); CloseHandle(fh); git_path_mkposix(filename); return filename; #else char *search_dirname, *search_filename, *filename = NULL; git_buf out = GIT_BUF_INIT; DIR *dir; struct dirent *de; cl_assert(search_dirname = git_path_dirname(in)); cl_assert(search_filename = git_path_basename(in)); cl_assert(dir = opendir(search_dirname)); while ((de = readdir(dir))) { if (strcasecmp(de->d_name, search_filename) == 0) { git_buf_join(&out, '/', search_dirname, de->d_name); filename = git_buf_detach(&out); break; } } closedir(dir); git__free(search_dirname); git__free(search_filename); git_buf_free(&out); return filename; #endif }
static int win32_path_to_8(git_buf *dest, const wchar_t *src) { git_win32_utf8_path utf8_path; if (git_win32_path_to_utf8(utf8_path, src) < 0) { giterr_set(GITERR_OS, "unable to convert path to UTF-8"); return -1; } /* Convert backslashes to forward slashes */ git_path_mkposix(utf8_path); return git_buf_sets(dest, utf8_path); }
char *p_realpath(const char *orig_path, char *buffer) { int ret, alloc = 0; if (buffer == NULL) { buffer = (char *)git__malloc(GIT_PATH_MAX); alloc = 1; } ret = GetFullPathName(orig_path, GIT_PATH_MAX, buffer, NULL); if (!ret || ret > GIT_PATH_MAX) { if (alloc) free(buffer); return NULL; } git_path_mkposix(buffer); return buffer; }
static int win32_find_file(git_buf *path, const struct win32_path *root, const char *filename) { int error = 0; size_t len; wchar_t *file_utf16 = NULL; char *file_utf8 = NULL; if (!root || !filename || (len = strlen(filename)) == 0) return GIT_ENOTFOUND; /* allocate space for wchar_t path to file */ file_utf16 = git__calloc(root->len + len + 2, 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++; if (gitwin_append_utf16(file_utf16 + root->len - 1, filename, len + 1) != (int)len + 1) { error = -1; goto cleanup; } /* check access */ if (_waccess(file_utf16, F_OK) < 0) { error = GIT_ENOTFOUND; goto cleanup; } /* convert to utf8 */ if ((file_utf8 = gitwin_from_utf16(file_utf16)) == NULL) error = -1; else { git_path_mkposix(file_utf8); git_buf_attach(path, file_utf8, 0); } cleanup: git__free(file_utf16); return error; }
int p_getcwd(char *buffer_out, size_t size) { char *cwd_buffer; assert(buffer_out && size > 0); #ifdef GIT_WIN32 cwd_buffer = _getcwd(buffer_out, size); #else cwd_buffer = getcwd(buffer_out, size); #endif if (cwd_buffer == NULL) return git__throw(GIT_EOSERR, "Failed to retrieve current working directory"); git_path_mkposix(buffer_out); git_path_join(buffer_out, buffer_out, ""); //Ensure the path ends with a trailing slash return GIT_SUCCESS; }