summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti <tanoku@gmail.com>2012-08-06 12:45:59 +0200
committerVicent Marti <tanoku@gmail.com>2012-08-28 23:09:43 -0700
commit6813169ac9fe2558e4503f0149f22c5fad9d61c1 (patch)
treee8bf85ab3b6578c4eab73de0ced96530c9a34f4c
parent3b73a03497e4fd67459960318308c9265bcd7805 (diff)
downloadlibgit2-6813169ac9fe2558e4503f0149f22c5fad9d61c1.tar.gz
windows: Keep UTF-8 on the stack yo
-rw-r--r--include/git2/windows.h59
-rw-r--r--src/fileops.c31
-rw-r--r--src/win32/dir.c29
-rw-r--r--src/win32/posix.h9
-rw-r--r--src/win32/posix_w32.c146
-rw-r--r--src/win32/utf-conv.c88
-rw-r--r--src/win32/utf-conv.h7
-rw-r--r--tests-clar/clar_helpers.c26
8 files changed, 87 insertions, 308 deletions
diff --git a/include/git2/windows.h b/include/git2/windows.h
deleted file mode 100644
index 8b743f0a..00000000
--- a/include/git2/windows.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2009-2012 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
-
diff --git a/src/fileops.c b/src/fileops.c
index 76ef8c91..6adccdd9 100644
--- a/src/fileops.c
+++ b/src/fileops.c
@@ -54,11 +54,10 @@ int git_futils_creat_locked(const char *path, const mode_t mode)
int fd;
#ifdef GIT_WIN32
- wchar_t* buf;
+ wchar_t buf[GIT_WIN_PATH];
- buf = gitwin_to_utf16(path);
+ git__utf8_to_16(buf, path);
fd = _wopen(buf, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_EXCL, mode);
- git__free(buf);
#else
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_EXCL, mode);
#endif
@@ -382,10 +381,9 @@ static int win32_expand_path(struct win32_path *s_root, const wchar_t *templ)
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;
+ char file_utf8[GIT_PATH_MAX];
if (!root || !filename || (len = strlen(filename)) == 0)
return GIT_ENOTFOUND;
@@ -400,29 +398,20 @@ static int win32_find_file(git_buf *path, const struct win32_path *root, const c
if (*filename == '/' || *filename == '\\')
filename++;
- if (gitwin_append_utf16(file_utf16 + root->len - 1, filename, len + 1) !=
- (int)len + 1) {
- error = -1;
- goto cleanup;
- }
+ git__utf8_to_16(file_utf16 + root->len - 1, filename);
/* check access */
if (_waccess(file_utf16, F_OK) < 0) {
- error = GIT_ENOTFOUND;
- goto cleanup;
+ git__free(file_utf16);
+ return GIT_ENOTFOUND;
}
- /* 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);
- }
+ git__utf16_to_8(file_utf8, file_utf16);
+ git_path_mkposix(file_utf8);
+ git_buf_sets(path, file_utf8);
-cleanup:
git__free(file_utf16);
- return error;
+ return 0;
}
#endif
diff --git a/src/win32/dir.c b/src/win32/dir.c
index bc3d40fa..8b4f8962 100644
--- a/src/win32/dir.c
+++ b/src/win32/dir.c
@@ -7,7 +7,6 @@
#define GIT__WIN32_NO_WRAP_DIR
#include "dir.h"
#include "utf-conv.h"
-#include "git2/windows.h"
static int init_filter(char *filter, size_t n, const char *dir)
{
@@ -26,8 +25,8 @@ static int init_filter(char *filter, size_t n, const char *dir)
git__DIR *git__opendir(const char *dir)
{
- char filter[4096];
- wchar_t* filter_w = NULL;
+ char filter[GIT_WIN_PATH];
+ wchar_t filter_w[GIT_WIN_PATH];
git__DIR *new = NULL;
if (!dir || !init_filter(filter, sizeof(filter), dir))
@@ -41,12 +40,8 @@ git__DIR *git__opendir(const char *dir)
if (!new->dir)
goto fail;
- filter_w = gitwin_to_utf16(filter);
- if (!filter_w)
- goto fail;
-
+ git__utf8_to_16(filter_w, filter);
new->h = FindFirstFileW(filter_w, &new->f);
- git__free(filter_w);
if (new->h == INVALID_HANDLE_VALUE) {
giterr_set(GITERR_OS, "Could not open directory '%s'", dir);
@@ -85,16 +80,9 @@ int git__readdir_ext(
if (wcslen(d->f.cFileName) >= sizeof(entry->d_name))
return -1;
+ git__utf16_to_8(entry->d_name, d->f.cFileName);
entry->d_ino = 0;
- if (WideCharToMultiByte(
- gitwin_get_codepage(), 0, d->f.cFileName, -1,
- entry->d_name, GIT_PATH_MAX, NULL, NULL) == 0)
- {
- giterr_set(GITERR_OS, "Could not convert filename to UTF-8");
- return -1;
- }
-
*result = entry;
if (is_dir != NULL)
@@ -113,8 +101,8 @@ struct git__dirent *git__readdir(git__DIR *d)
void git__rewinddir(git__DIR *d)
{
- char filter[4096];
- wchar_t* filter_w;
+ char filter[GIT_WIN_PATH];
+ wchar_t filter_w[GIT_WIN_PATH];
if (!d)
return;
@@ -125,12 +113,11 @@ void git__rewinddir(git__DIR *d)
d->first = 0;
}
- if (!init_filter(filter, sizeof(filter), d->dir) ||
- (filter_w = gitwin_to_utf16(filter)) == NULL)
+ if (!init_filter(filter, sizeof(filter), d->dir))
return;
+ git__utf8_to_16(filter_w, filter);
d->h = FindFirstFileW(filter_w, &d->f);
- git__free(filter_w);
if (d->h == INVALID_HANDLE_VALUE)
giterr_set(GITERR_OS, "Could not open directory '%s'", d->dir);
diff --git a/src/win32/posix.h b/src/win32/posix.h
index 14caae41..ddab88a3 100644
--- a/src/win32/posix.h
+++ b/src/win32/posix.h
@@ -21,13 +21,10 @@ GIT_INLINE(int) p_link(const char *old, const char *new)
GIT_INLINE(int) p_mkdir(const char *path, mode_t mode)
{
- wchar_t* buf = gitwin_to_utf16(path);
- int ret = _wmkdir(buf);
-
+ wchar_t buf[GIT_WIN_PATH];
GIT_UNUSED(mode);
-
- git__free(buf);
- return ret;
+ git__utf8_to_16(buf, path);
+ return _wmkdir(buf);
}
extern int p_unlink(const char *path);
diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c
index aa34ad3a..682a40ad 100644
--- a/src/win32/posix_w32.c
+++ b/src/win32/posix_w32.c
@@ -15,16 +15,10 @@
int p_unlink(const char *path)
{
- int ret = 0;
- wchar_t* buf;
-
- if ((buf = gitwin_to_utf16(path)) != NULL) {
- _wchmod(buf, 0666);
- ret = _wunlink(buf);
- git__free(buf);
- }
-
- return ret;
+ wchar_t buf[GIT_WIN_PATH];
+ git__utf8_to_16(buf, path);
+ _wchmod(buf, 0666);
+ return _wunlink(buf);
}
int p_fsync(int fd)
@@ -61,10 +55,10 @@ 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[GIT_WIN_PATH];
DWORD last_error;
- wchar_t* fbuf = gitwin_to_utf16(file_name);
- if (!fbuf)
- return -1;
+
+ git__utf8_to_16(fbuf, file_name);
if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
int fMode = S_IREAD;
@@ -90,8 +84,6 @@ static int do_lstat(const char *file_name, struct stat *buf)
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
-
- git__free(fbuf);
return 0;
}
@@ -101,7 +93,6 @@ static int do_lstat(const char *file_name, struct stat *buf)
else if (last_error == ERROR_PATH_NOT_FOUND)
errno = ENOTDIR;
- git__free(fbuf);
return -1;
}
@@ -143,7 +134,7 @@ int p_readlink(const char *link, char *target, size_t target_len)
static fpath_func pGetFinalPath = NULL;
HANDLE hFile;
DWORD dwRet;
- wchar_t* link_w;
+ wchar_t link_w[GIT_WIN_PATH];
wchar_t* target_w;
int error = 0;
@@ -166,8 +157,7 @@ int p_readlink(const char *link, char *target, size_t target_len)
}
}
- link_w = gitwin_to_utf16(link);
- GITERR_CHECK_ALLOC(link_w);
+ git__utf8_to_16(link_w, link);
hFile = CreateFileW(link_w, // file to open
GENERIC_READ, // open for reading
@@ -177,8 +167,6 @@ int p_readlink(const char *link, char *target, size_t target_len)
FILE_FLAG_BACKUP_SEMANTICS, // normal file
NULL); // no attr. template
- git__free(link_w);
-
if (hFile == INVALID_HANDLE_VALUE) {
giterr_set(GITERR_OS, "Cannot open '%s' for reading", link);
return -1;
@@ -235,16 +223,12 @@ int p_symlink(const char *old, const char *new)
int p_open(const char *path, int flags, ...)
{
- int fd;
- wchar_t* buf;
+ wchar_t buf[GIT_WIN_PATH];
mode_t mode = 0;
- buf = gitwin_to_utf16(path);
- if (!buf)
- return -1;
+ git__utf8_to_16(buf, path);
- if (flags & O_CREAT)
- {
+ if (flags & O_CREAT) {
va_list arg_list;
va_start(arg_list, flags);
@@ -252,27 +236,20 @@ int p_open(const char *path, int flags, ...)
va_end(arg_list);
}
- fd = _wopen(buf, flags | _O_BINARY, mode);
-
- git__free(buf);
- return fd;
+ return _wopen(buf, flags | _O_BINARY, mode);
}
int p_creat(const char *path, mode_t mode)
{
- int fd;
- wchar_t* buf = gitwin_to_utf16(path);
- if (!buf)
- return -1;
- fd = _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode);
- git__free(buf);
- return fd;
+ wchar_t buf[GIT_WIN_PATH];
+ git__utf8_to_16(buf, path);
+ return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode);
}
int p_getcwd(char *buffer_out, size_t size)
{
int ret;
- wchar_t* buf;
+ wchar_t *buf;
if ((size_t)((int)size) != size)
return -1;
@@ -296,64 +273,43 @@ int p_stat(const char* path, struct stat* buf)
int p_chdir(const char* path)
{
- wchar_t* buf = gitwin_to_utf16(path);
- int ret;
- if (!buf)
- return -1;
- ret = _wchdir(buf);
- git__free(buf);
- return ret;
+ wchar_t buf[GIT_WIN_PATH];
+ git__utf8_to_16(buf, path);
+ return _wchdir(buf);
}
int p_chmod(const char* path, mode_t mode)
{
- wchar_t* buf = gitwin_to_utf16(path);
- int ret;
- if (!buf)
- return -1;
- ret = _wchmod(buf, mode);
- git__free(buf);
- return ret;
+ wchar_t buf[GIT_WIN_PATH];
+ git__utf8_to_16(buf, path);
+ return _wchmod(buf, mode);
}
int p_rmdir(const char* path)
{
- wchar_t* buf = gitwin_to_utf16(path);
- int ret;
- if (!buf)
- return -1;
- ret = _wrmdir(buf);
- git__free(buf);
- return ret;
+ wchar_t buf[GIT_WIN_PATH];
+ git__utf8_to_16(buf, path);
+ return _wrmdir(buf);
}
int p_hide_directory__w32(const char *path)
{
- int res;
- wchar_t* buf = gitwin_to_utf16(path);
- if (!buf)
- return -1;
-
- res = SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN);
- git__free(buf);
-
- return (res != 0) ? 0 : -1; /* MSDN states a "non zero" value indicates a success */
+ wchar_t buf[GIT_WIN_PATH];
+ git__utf8_to_16(buf, path);
+ return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1;
}
char *p_realpath(const char *orig_path, char *buffer)
{
int ret, buffer_sz = 0;
- 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 (!orig_path_w || !buffer_w)
- return NULL;
+ wchar_t orig_path_w[GIT_WIN_PATH];
+ wchar_t buffer_w[GIT_WIN_PATH];
- ret = GetFullPathNameW(orig_path_w, GIT_PATH_MAX, buffer_w, NULL);
- git__free(orig_path_w);
+ git__utf8_to_16(orig_path_w, orig_path);
+ ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH, buffer_w, NULL);
/* According to MSDN, a return value equals to zero means a failure. */
- if (ret == 0 || ret > GIT_PATH_MAX) {
+ if (ret == 0 || ret > GIT_WIN_PATH) {
buffer = NULL;
goto done;
}
@@ -376,8 +332,7 @@ char *p_realpath(const char *orig_path, char *buffer)
}
}
- if (!git_path_exists(buffer))
- {
+ if (!git_path_exists(buffer)) {
if (buffer_sz > 0)
git__free(buffer);
@@ -386,9 +341,9 @@ char *p_realpath(const char *orig_path, char *buffer)
}
done:
- git__free(buffer_w);
if (buffer)
git_path_mkposix(buffer);
+
return buffer;
}
@@ -443,32 +398,19 @@ int p_setenv(const char* name, const char* value, int overwrite)
int p_access(const char* path, mode_t mode)
{
- wchar_t *buf = gitwin_to_utf16(path);
- int ret;
- if (!buf)
- return -1;
-
- ret = _waccess(buf, mode);
- git__free(buf);
-
- return ret;
+ wchar_t buf[GIT_WIN_PATH];
+ git__utf8_to_16(buf, path);
+ return _waccess(buf, mode);
}
int p_rename(const char *from, const char *to)
{
- wchar_t *wfrom = gitwin_to_utf16(from);
- wchar_t *wto = gitwin_to_utf16(to);
- int ret;
-
- if (!wfrom || !wto)
- return -1;
-
- ret = MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1;
-
- git__free(wfrom);
- git__free(wto);
+ wchar_t wfrom[GIT_WIN_PATH];
+ wchar_t wto[GIT_WIN_PATH];
- return ret;
+ git__utf8_to_16(wfrom, from);
+ git__utf8_to_16(wto, to);
+ return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1;
}
int p_recv(GIT_SOCKET socket, void *buffer, size_t length, int flags)
diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c
index 4b95001d..a98e814f 100644
--- a/src/win32/utf-conv.c
+++ b/src/win32/utf-conv.c
@@ -7,39 +7,18 @@
#include "common.h"
#include "utf-conv.h"
-#include "git2/windows.h"
-
-/*
- * 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;
-}
#define U16_LEAD(c) (wchar_t)(((c)>>10)+0xd7c0)
#define U16_TRAIL(c) (wchar_t)(((c)&0x3ff)|0xdc00)
-void git__utf8_to_16(wchar_t *dest, const char *src, size_t srcLength)
+void git__utf8_to_16(wchar_t *dest, const char *src)
{
wchar_t *pDest = dest;
uint32_t ch;
const uint8_t* pSrc = (uint8_t*) src;
- const uint8_t *pSrcLimit = pSrc + srcLength;
+ const uint8_t *pSrcLimit = pSrc + strlen(src);
- assert(dest && src && srcLength > 0);
+ assert(dest && src);
if ((pSrcLimit - pSrc) >= 4) {
pSrcLimit -= 3; /* temporarily reduce pSrcLimit */
@@ -121,64 +100,7 @@ void git__utf8_to_16(wchar_t *dest, const char *src, size_t srcLength)
*pDest++ = 0x0;
}
-wchar_t* gitwin_to_utf16(const char* str)
+void git__utf16_to_8(char *out, const wchar_t *input)
{
- wchar_t* ret;
- int cb;
-
- if (!str)
- return NULL;
-
- cb = MultiByteToWideChar(_active_codepage, 0, str, -1, NULL, 0);
- if (cb == 0)
- return (wchar_t *)git__calloc(1, sizeof(wchar_t));
-
- ret = (wchar_t *)git__malloc(cb * sizeof(wchar_t));
- if (!ret)
- return NULL;
-
- if (MultiByteToWideChar(_active_codepage, 0, str, -1, ret, (int)cb) == 0) {
- giterr_set(GITERR_OS, "Could not convert string to UTF-16");
- git__free(ret);
- ret = NULL;
- }
-
- return ret;
-}
-
-int gitwin_append_utf16(wchar_t *buffer, const char *str, size_t len)
-{
- int result = MultiByteToWideChar(
- _active_codepage, 0, str, -1, buffer, (int)len);
- if (result == 0)
- giterr_set(GITERR_OS, "Could not convert string to UTF-16");
- return result;
-}
-
-char* gitwin_from_utf16(const wchar_t* str)
-{
- char* ret;
- int cb;
-
- if (!str)
- return NULL;
-
- cb = WideCharToMultiByte(_active_codepage, 0, str, -1, NULL, 0, NULL, NULL);
- if (cb == 0)
- return (char *)git__calloc(1, sizeof(char));
-
- ret = (char*)git__malloc(cb);
- if (!ret)
- return NULL;
-
- if (WideCharToMultiByte(
- _active_codepage, 0, str, -1, ret, (int)cb, NULL, NULL) == 0)
- {
- giterr_set(GITERR_OS, "Could not convert string to UTF-8");
- git__free(ret);
- ret = NULL;
- }
-
- return ret;
-
+ WideCharToMultiByte(CP_UTF8, 0, input, -1, out, GIT_WIN_PATH, NULL, NULL);
}
diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h
index ae9f29f6..c0cfffe4 100644
--- a/src/win32/utf-conv.h
+++ b/src/win32/utf-conv.h
@@ -10,9 +10,10 @@
#ifndef INCLUDE_git_utfconv_h__
#define INCLUDE_git_utfconv_h__
-wchar_t* gitwin_to_utf16(const char* str);
-int gitwin_append_utf16(wchar_t *buffer, const char *str, size_t len);
-char* gitwin_from_utf16(const wchar_t* str);
+#define GIT_WIN_PATH (260 + 1)
+
+void git__utf8_to_16(wchar_t *dest, const char *src);
+void git__utf16_to_8(char *dest, const wchar_t *src);
#endif
diff --git a/tests-clar/clar_helpers.c b/tests-clar/clar_helpers.c
index c9147943..125f7855 100644
--- a/tests-clar/clar_helpers.c
+++ b/tests-clar/clar_helpers.c
@@ -55,22 +55,23 @@ void cl_git_rewritefile(const char *filename, const char *new_content)
char *cl_getenv(const char *name)
{
- wchar_t *name_utf16 = gitwin_to_utf16(name);
- DWORD value_len, alloc_len;
+ wchar_t name_utf16[GIT_WIN_PATH];
+ DWORD alloc_len;
wchar_t *value_utf16;
char *value_utf8;
- cl_assert(name_utf16);
+ git__utf8_to_16(name_utf16, name);
alloc_len = GetEnvironmentVariableW(name_utf16, NULL, 0);
if (alloc_len <= 0)
return NULL;
+ alloc_len = GIT_WIN_PATH;
cl_assert(value_utf16 = git__calloc(alloc_len, sizeof(wchar_t)));
- value_len = GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len);
- cl_assert_equal_i(value_len, alloc_len - 1);
+ GetEnvironmentVariableW(name_utf16, value_utf16, alloc_len);
- cl_assert(value_utf8 = gitwin_from_utf16(value_utf16));
+ cl_assert(value_utf8 = git__malloc(alloc_len));
+ git__utf16_to_8(value_utf8, value_utf16);
git__free(value_utf16);
@@ -79,17 +80,16 @@ char *cl_getenv(const char *name)
int cl_setenv(const char *name, const char *value)
{
- wchar_t *name_utf16 = gitwin_to_utf16(name);
- wchar_t *value_utf16 = value ? gitwin_to_utf16(value) : NULL;
+ wchar_t name_utf16[GIT_WIN_PATH];
+ wchar_t value_utf16[GIT_WIN_PATH];
- cl_assert(name_utf16);
- cl_assert(SetEnvironmentVariableW(name_utf16, value_utf16));
+ git__utf8_to_16(name_utf16, name);
- git__free(name_utf16);
- git__free(value_utf16);
+ if (value != NULL)
+ git__utf8_to_16(value_utf16, value);
+ cl_assert(SetEnvironmentVariableW(name_utf16, value ? value_utf16 : NULL));
return 0;
-
}
#else