int git_win32_path_from_utf8(git_win32_path out, const char *src) { wchar_t *dest = out; /* All win32 paths are in NT-prefixed format, beginning with "\\?\". */ memcpy(dest, PATH__NT_NAMESPACE, sizeof(wchar_t) * PATH__NT_NAMESPACE_LEN); dest += PATH__NT_NAMESPACE_LEN; /* See if this is an absolute path (beginning with a drive letter) */ if (path__is_absolute(src)) { if (git__utf8_to_16(dest, MAX_PATH, src) < 0) return -1; } /* File-prefixed NT-style paths beginning with \\?\ */ else if (path__is_nt_namespace(src)) { /* Skip the NT prefix, the destination already contains it */ if (git__utf8_to_16(dest, MAX_PATH, src + PATH__NT_NAMESPACE_LEN) < 0) return -1; } /* UNC paths */ else if (path__is_unc(src)) { memcpy(dest, L"UNC\\", sizeof(wchar_t) * 4); dest += 4; /* Skip the leading "\\" */ if (git__utf8_to_16(dest, MAX_PATH - 2, src + 2) < 0) return -1; } /* Absolute paths omitting the drive letter */ else if (src[0] == '\\' || src[0] == '/') { if (path__cwd(dest, MAX_PATH) < 0) return -1; if (!path__is_absolute(dest)) { errno = ENOENT; return -1; } /* Skip the drive letter specification ("C:") */ if (git__utf8_to_16(dest + 2, MAX_PATH - 2, src) < 0) return -1; } /* Relative paths */ else { int cwd_len; if ((cwd_len = git_win32_path__cwd(dest, MAX_PATH)) < 0) return -1; dest[cwd_len++] = L'\\'; if (git__utf8_to_16(dest + cwd_len, MAX_PATH - cwd_len, src) < 0) return -1; } return git_win32_path_canonicalize(out); }
static wchar_t *path__skip_prefix(wchar_t *path) { if (path__is_nt_namespace(path)) { path += PATH__NT_NAMESPACE_LEN; if (wcsncmp(path, L"UNC\\", 4) == 0) path = path__skip_server(path + 4); else if (path__is_absolute(path)) path += PATH__ABSOLUTE_LEN; } else if (path__is_absolute(path)) { path += PATH__ABSOLUTE_LEN; } else if (path__is_unc(path)) { path = path__skip_server(path + 2); } return path; }