Commit 11d51ca6 by Vicent Marti Committed by Carlos Martín Nieto

windows: Add support for non-UTF codepages

Our previous assumption that all paths in Windows are encoded in UTF-8
is rather weak, specially when considering that Git is
encoding-agnostic.

These set of functions allow the user to change the library's active
codepage globally, so it is possible to access paths and files on all
international versions of Windows.

Note that the default encoding here is UTF-8 because we assume that 99%
of all Git repositories will be in UTF-8.

Also, if you use non-ascii characters in paths, anywhere, please burn on
a fire.
parent c2fbe423
/*
* Copyright (C) 2009-2011 the libgit2 contributors
*
* This file is part of libgit2, distributed under the GNU GPL v2 with
* a Linking Exception. For full terms see the included COPYING file.
*/
#ifndef INCLUDE_git_windows_h__
#define INCLUDE_git_windows_h__
#include "common.h"
/**
* @file git2/windows.h
* @brief Windows-specific functions
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/**
* Set the active codepage for Windows syscalls
*
* All syscalls performed by the library will assume
* this codepage when converting paths and strings
* to use by the Windows kernel.
*
* The default value of UTF-8 will work automatically
* with most Git repositories created on Unix systems.
*
* This settings needs only be changed when working
* with repositories that contain paths in specific,
* non-UTF codepages.
*
* A full list of all available codepage identifiers may
* be found at:
*
* http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx
*
* @param codepage numeric codepage identifier
*/
GIT_EXTERN(void) gitwin_set_codepage(unsigned int codepage);
/**
* Return the active codepage for Windows syscalls
*
* @return numeric codepage identifier
*/
GIT_EXTERN(unsigned int) gitwin_get_codepage(void);
/**
* Set the active Windows codepage to UTF-8 (this is
* the default value)
*/
GIT_EXTERN(void) gitwin_set_utf8(void);
/** @} */
GIT_END_DECL
#endif
......@@ -370,7 +370,7 @@ static int win32_find_system(char *system_config_path)
return GIT_ENOTFOUND;
}
apphome_utf8 = conv_utf16_to_utf8(apphome_utf16);
apphome_utf8 = gitwin_from_utf16(apphome_utf16);
free(apphome_utf16);
if (strlen(apphome_utf8) >= GIT_PATH_MAX) {
......
......@@ -6,7 +6,8 @@
*/
#define GIT__WIN32_NO_WRAP_DIR
#include "dir.h"
#include "utf8-conv.h"
#include "utf-conv.h"
#include "git2/windows.h"
static int init_filter(char *filter, size_t n, const char *dir)
{
......@@ -43,7 +44,7 @@ git__DIR *git__opendir(const char *dir)
}
strcpy(new->dir, dir);
filter_w = conv_utf8_to_utf16(filter);
filter_w = gitwin_to_utf16(filter);
new->h = FindFirstFileW(filter_w, &new->f);
free(filter_w);
......@@ -73,7 +74,7 @@ struct git__dirent *git__readdir(git__DIR *d)
return NULL;
d->entry.d_ino = 0;
WideCharToMultiByte(CP_UTF8, 0, d->f.cFileName, -1, d->entry.d_name, GIT_PATH_MAX, NULL, NULL);
WideCharToMultiByte(gitwin_get_codepage(), 0, d->f.cFileName, -1, d->entry.d_name, GIT_PATH_MAX, NULL, NULL);
return &d->entry;
}
......@@ -90,7 +91,7 @@ void git__rewinddir(git__DIR *d)
d->first = 0;
if (init_filter(filter, sizeof(filter), d->dir)) {
filter_w = conv_utf8_to_utf16(filter);
filter_w = gitwin_to_utf16(filter);
d->h = FindFirstFileW(filter_w, &d->f);
free(filter_w);
......
......@@ -9,7 +9,7 @@
#include "common.h"
#include "fnmatch.h"
#include "utf8-conv.h"
#include "utf-conv.h"
GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
{
......@@ -21,7 +21,7 @@ GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
GIT_INLINE(int) p_mkdir(const char *path, int GIT_UNUSED(mode))
{
wchar_t* buf = conv_utf8_to_utf16(path);
wchar_t* buf = gitwin_to_utf16(path);
int ret = _wmkdir(buf);
GIT_UNUSED_ARG(mode)
......
......@@ -6,7 +6,7 @@
*/
#include "posix.h"
#include "path.h"
#include "utf8-conv.h"
#include "utf-conv.h"
#include <errno.h>
#include <io.h>
#include <fcntl.h>
......@@ -17,7 +17,7 @@ int p_unlink(const char *path)
int ret = 0;
wchar_t* buf;
buf = conv_utf8_to_utf16(path);
buf = gitwin_to_utf16(path);
_wchmod(buf, 0666);
ret = _wunlink(buf);
free(buf);
......@@ -59,7 +59,7 @@ GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
static int do_lstat(const char *file_name, struct stat *buf)
{
WIN32_FILE_ATTRIBUTE_DATA fdata;
wchar_t* fbuf = conv_utf8_to_utf16(file_name);
wchar_t* fbuf = gitwin_to_utf16(file_name);
if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
int fMode = S_IREAD;
......@@ -161,7 +161,7 @@ int p_readlink(const char *link, char *target, size_t target_len)
"'GetFinalPathNameByHandleW' is not available in this platform");
}
link_w = conv_utf8_to_utf16(link);
link_w = gitwin_to_utf16(link);
hFile = CreateFileW(link_w, // file to open
GENERIC_READ, // open for reading
......@@ -223,7 +223,7 @@ int p_readlink(const char *link, char *target, size_t target_len)
int p_open(const char *path, int flags)
{
int fd;
wchar_t* buf = conv_utf8_to_utf16(path);
wchar_t* buf = gitwin_to_utf16(path);
fd = _wopen(buf, flags | _O_BINARY);
free(buf);
......@@ -233,7 +233,7 @@ int p_open(const char *path, int flags)
int p_creat(const char *path, int mode)
{
int fd;
wchar_t* buf = conv_utf8_to_utf16(path);
wchar_t* buf = gitwin_to_utf16(path);
fd = _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode);
free(buf);
......@@ -261,7 +261,7 @@ int p_stat(const char* path, struct stat* buf)
int p_chdir(const char* path)
{
wchar_t* buf = conv_utf8_to_utf16(path);
wchar_t* buf = gitwin_to_utf16(path);
int ret = _wchdir(buf);
free(buf);
......@@ -270,7 +270,7 @@ int p_chdir(const char* path)
int p_chmod(const char* path, int mode)
{
wchar_t* buf = conv_utf8_to_utf16(path);
wchar_t* buf = gitwin_to_utf16(path);
int ret = _wchmod(buf, mode);
free(buf);
......@@ -279,7 +279,7 @@ int p_chmod(const char* path, int mode)
int p_rmdir(const char* path)
{
wchar_t* buf = conv_utf8_to_utf16(path);
wchar_t* buf = gitwin_to_utf16(path);
int ret = _wrmdir(buf);
free(buf);
......@@ -289,7 +289,7 @@ int p_rmdir(const char* path)
int p_hide_directory__w32(const char *path)
{
int error;
wchar_t* buf = conv_utf8_to_utf16(path);
wchar_t* buf = gitwin_to_utf16(path);
error = SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0 ?
GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
......@@ -305,7 +305,7 @@ int p_hide_directory__w32(const char *path)
char *p_realpath(const char *orig_path, char *buffer)
{
int ret, alloc = 0;
wchar_t* orig_path_w = conv_utf8_to_utf16(orig_path);
wchar_t* orig_path_w = gitwin_to_utf16(orig_path);
wchar_t* buffer_w = (wchar_t*)git__malloc(GIT_PATH_MAX * sizeof(wchar_t));
if (buffer == NULL) {
......@@ -380,7 +380,7 @@ int p_setenv(const char* name, const char* value, int overwrite)
int p_access(const char* path, int mode)
{
wchar_t *buf = conv_utf8_to_utf16(path);
wchar_t *buf = gitwin_to_utf16(path);
int ret;
ret = _waccess(buf, mode);
......
......@@ -6,9 +6,29 @@
*/
#include "common.h"
#include "utf8-conv.h"
#include "utf-conv.h"
wchar_t* conv_utf8_to_utf16(const char* str)
/*
* Default codepage value
*/
static int _active_codepage = CP_UTF8;
void gitwin_set_codepage(unsigned int codepage)
{
_active_codepage = codepage;
}
unsigned int gitwin_get_codepage(void)
{
return _active_codepage;
}
void gitwin_set_utf8(void)
{
_active_codepage = CP_UTF8;
}
wchar_t* gitwin_to_utf16(const char* str)
{
wchar_t* ret;
int cb;
......@@ -29,7 +49,7 @@ wchar_t* conv_utf8_to_utf16(const char* str)
ret = (wchar_t*)git__malloc(cb);
if (MultiByteToWideChar(CP_UTF8, 0, str, -1, ret, cb) == 0) {
if (MultiByteToWideChar(_active_codepage, 0, str, -1, ret, cb) == 0) {
free(ret);
ret = NULL;
}
......@@ -37,7 +57,7 @@ wchar_t* conv_utf8_to_utf16(const char* str)
return ret;
}
char* conv_utf16_to_utf8(const wchar_t* str)
char* gitwin_from_utf16(const wchar_t* str)
{
char* ret;
int cb;
......@@ -58,7 +78,7 @@ char* conv_utf16_to_utf8(const wchar_t* str)
ret = (char*)git__malloc(cb);
if (WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, cb, NULL, NULL) == 0) {
if (WideCharToMultiByte(_active_codepage, 0, str, -1, ret, cb, NULL, NULL) == 0) {
free(ret);
ret = NULL;
}
......
......@@ -7,11 +7,11 @@
#include <wchar.h>
#ifndef INCLUDE_git_utf8conv_h__
#define INCLUDE_git_utf8conv_h__
#ifndef INCLUDE_git_utfconv_h__
#define INCLUDE_git_utfconv_h__
wchar_t* conv_utf8_to_utf16(const char* str);
char* conv_utf16_to_utf8(const wchar_t* str);
wchar_t* gitwin_to_utf16(const char* str);
char* gitwin_from_utf16(const wchar_t* str);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment