Commit 7998ae5a by Paul Betts

Rewrite p_* functions to use Unicode and marshal to UTF8 internally

parent c498701d
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <stdio.h> #include <stdio.h>
#include <ctype.h> #include <ctype.h>
#ifndef GIT_WIN32
int p_open(const char *path, int flags) int p_open(const char *path, int flags)
{ {
return open(path, flags | O_BINARY); return open(path, flags | O_BINARY);
...@@ -20,6 +22,25 @@ int p_creat(const char *path, int mode) ...@@ -20,6 +22,25 @@ int p_creat(const char *path, int mode)
return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode); return open(path, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
} }
int p_getcwd(char *buffer_out, size_t size)
{
char *cwd_buffer;
assert(buffer_out && size > 0);
cwd_buffer = getcwd(buffer_out, size);
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;
}
#endif
int p_read(git_file fd, void *buf, size_t cnt) int p_read(git_file fd, void *buf, size_t cnt)
{ {
char *b = buf; char *b = buf;
...@@ -57,24 +78,3 @@ int p_write(git_file fd, const void *buf, size_t cnt) ...@@ -57,24 +78,3 @@ int p_write(git_file fd, const void *buf, size_t cnt)
} }
return GIT_SUCCESS; return GIT_SUCCESS;
} }
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;
}
...@@ -33,19 +33,26 @@ typedef int git_file; ...@@ -33,19 +33,26 @@ typedef int git_file;
* Use your manpages to check the docs on these. * Use your manpages to check the docs on these.
* Straightforward * Straightforward
*/ */
extern int p_open(const char *path, int flags);
extern int p_creat(const char *path, int mode);
extern int p_read(git_file fd, void *buf, size_t cnt); extern int p_read(git_file fd, void *buf, size_t cnt);
extern int p_write(git_file fd, const void *buf, size_t cnt); extern int p_write(git_file fd, const void *buf, size_t cnt);
extern int p_getcwd(char *buffer_out, size_t size);
#define p_fstat(f,b) fstat(f, b)
#define p_lseek(f,n,w) lseek(f, n, w) #define p_lseek(f,n,w) lseek(f, n, w)
#define p_close(fd) close(fd)
extern int p_open(const char *path, int flags);
extern int p_creat(const char *path, int mode);
extern int p_getcwd(char *buffer_out, size_t size);
#ifndef GIT_WIN32
#define p_stat(p,b) stat(p, b) #define p_stat(p,b) stat(p, b)
#define p_fstat(f,b) fstat(f, b)
#define p_chdir(p) chdir(p) #define p_chdir(p) chdir(p)
#define p_rmdir(p) rmdir(p) #define p_rmdir(p) rmdir(p)
#define p_chmod(p,m) chmod(p, m) #define p_chmod(p,m) chmod(p, m)
#define p_close(fd) close(fd)
#endif
/** /**
* Platform-dependent methods * Platform-dependent methods
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
*/ */
#define GIT__WIN32_NO_WRAP_DIR #define GIT__WIN32_NO_WRAP_DIR
#include "dir.h" #include "dir.h"
#include "utf8-conv.h"
static int init_filter(char *filter, size_t n, const char *dir) static int init_filter(char *filter, size_t n, const char *dir)
{ {
......
...@@ -6,13 +6,23 @@ ...@@ -6,13 +6,23 @@
*/ */
#include "posix.h" #include "posix.h"
#include "path.h" #include "path.h"
#include "utf8-conv.h"
#include <errno.h> #include <errno.h>
#include <io.h> #include <io.h>
#include <fcntl.h>
int p_unlink(const char *path) int p_unlink(const char *path)
{ {
chmod(path, 0666); int ret = 0;
return unlink(path); wchar_t* buf;
buf = conv_utf8_to_utf16(path);
_wchmod(buf, 0666);
ret = _wunlink(buf);
free(buf);
return ret;
} }
int p_fsync(int fd) int p_fsync(int fd)
...@@ -49,8 +59,9 @@ GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft) ...@@ -49,8 +59,9 @@ GIT_INLINE(time_t) filetime_to_time_t(const FILETIME *ft)
static int do_lstat(const char *file_name, struct stat *buf) static int do_lstat(const char *file_name, struct stat *buf)
{ {
WIN32_FILE_ATTRIBUTE_DATA fdata; WIN32_FILE_ATTRIBUTE_DATA fdata;
wchar_t* fbuf = conv_utf8_to_utf16(file_name);
if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) { if (GetFileAttributesExW(fbuf, GetFileExInfoStandard, &fdata)) {
int fMode = S_IREAD; int fMode = S_IREAD;
if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
...@@ -74,22 +85,26 @@ static int do_lstat(const char *file_name, struct stat *buf) ...@@ -74,22 +85,26 @@ static int do_lstat(const char *file_name, struct stat *buf)
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
free(fbuf);
return GIT_SUCCESS; return GIT_SUCCESS;
} }
switch (GetLastError()) { free(fbuf);
case ERROR_ACCESS_DENIED:
case ERROR_SHARING_VIOLATION:
case ERROR_LOCK_VIOLATION:
case ERROR_SHARING_BUFFER_EXCEEDED:
return GIT_EOSERR;
case ERROR_BUFFER_OVERFLOW:
case ERROR_NOT_ENOUGH_MEMORY:
return GIT_ENOMEM;
default: switch (GetLastError()) {
return GIT_EINVALIDPATH; case ERROR_ACCESS_DENIED:
case ERROR_SHARING_VIOLATION:
case ERROR_LOCK_VIOLATION:
case ERROR_SHARING_BUFFER_EXCEEDED:
return GIT_EOSERR;
case ERROR_BUFFER_OVERFLOW:
case ERROR_NOT_ENOUGH_MEMORY:
return GIT_ENOMEM;
default:
return GIT_EINVALIDPATH;
} }
} }
...@@ -124,10 +139,12 @@ int p_lstat(const char *file_name, struct stat *buf) ...@@ -124,10 +139,12 @@ int p_lstat(const char *file_name, struct stat *buf)
int p_readlink(const char *link, char *target, size_t target_len) int p_readlink(const char *link, char *target, size_t target_len)
{ {
typedef DWORD (WINAPI *fpath_func)(HANDLE, LPTSTR, DWORD, DWORD); typedef DWORD (WINAPI *fpath_func)(HANDLE, LPWSTR, DWORD, DWORD);
static fpath_func pGetFinalPath = NULL; static fpath_func pGetFinalPath = NULL;
HANDLE hFile; HANDLE hFile;
DWORD dwRet; DWORD dwRet;
wchar_t* link_w;
wchar_t* target_w;
/* /*
* Try to load the pointer to pGetFinalPath dynamically, because * Try to load the pointer to pGetFinalPath dynamically, because
...@@ -137,28 +154,47 @@ int p_readlink(const char *link, char *target, size_t target_len) ...@@ -137,28 +154,47 @@ int p_readlink(const char *link, char *target, size_t target_len)
HINSTANCE library = LoadLibrary("kernel32"); HINSTANCE library = LoadLibrary("kernel32");
if (library != NULL) if (library != NULL)
pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleA"); pGetFinalPath = (fpath_func)GetProcAddress(library, "GetFinalPathNameByHandleW");
if (pGetFinalPath == NULL) if (pGetFinalPath == NULL)
return git__throw(GIT_EOSERR, return git__throw(GIT_EOSERR,
"'GetFinalPathNameByHandleA' is not available in this platform"); "'GetFinalPathNameByHandleW' is not available in this platform");
} }
hFile = CreateFile(link, // file to open link_w = conv_utf8_to_utf16(link);
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading hFile = CreateFileW(link_w, // file to open
NULL, // default security GENERIC_READ, // open for reading
OPEN_EXISTING, // existing file only FILE_SHARE_READ, // share for reading
FILE_FLAG_BACKUP_SEMANTICS, // normal file NULL, // default security
NULL); // no attr. template OPEN_EXISTING, // existing file only
FILE_FLAG_BACKUP_SEMANTICS, // normal file
NULL); // no attr. template
free(link_w);
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
return GIT_EOSERR; return GIT_EOSERR;
dwRet = pGetFinalPath(hFile, target, target_len, 0x0); if (target_len <= 0) {
if (dwRet >= target_len) return GIT_EINVALIDARGS;
}
target_w = (wchar_t*)git__malloc(target_len * sizeof(wchar_t));
dwRet = pGetFinalPath(hFile, target_w, target_len, 0x0);
if (dwRet >= target_len) {
free(target_w);
CloseHandle(hFile);
return GIT_ENOMEM; return GIT_ENOMEM;
}
if (!WideCharToMultiByte(CP_UTF8, 0, target_w, -1, target, target_len * sizeof(char), NULL, NULL)) {
free(target_w);
return GIT_EOSERR;
}
free(target_w);
CloseHandle(hFile); CloseHandle(hFile);
if (dwRet > 4) { if (dwRet > 4) {
...@@ -184,13 +220,82 @@ int p_readlink(const char *link, char *target, size_t target_len) ...@@ -184,13 +220,82 @@ int p_readlink(const char *link, char *target, size_t target_len)
return dwRet; return dwRet;
} }
int p_open(const char *path, int flags)
{
int fd;
wchar_t* buf = conv_utf8_to_utf16(path);
fd = _wopen(buf, flags | _O_BINARY);
free(buf);
return fd;
}
int p_creat(const char *path, int mode)
{
int fd;
wchar_t* buf = conv_utf8_to_utf16(path);
fd = _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode);
free(buf);
return fd;
}
int p_getcwd(char *buffer_out, size_t size)
{
wchar_t* buf = (wchar_t*)git__malloc(sizeof(wchar_t) * (int)size);
_wgetcwd(buf, (int)size);
if (!WideCharToMultiByte(CP_UTF8, 0, buf, -1, buffer_out, size, NULL, NULL)) {
free(buf);
return GIT_EOSERR;
}
free(buf);
return GIT_SUCCESS;
}
int p_stat(const char* path, struct stat* buf)
{
return do_lstat(path, buf);
}
int p_chdir(const char* path)
{
wchar_t* buf = conv_utf8_to_utf16(path);
int ret = _wchdir(buf);
free(buf);
return ret;
}
int p_chmod(const char* path, int mode)
{
wchar_t* buf = conv_utf8_to_utf16(path);
int ret = _wchmod(buf, mode);
free(buf);
return ret;
}
int p_rmdir(const char* path)
{
wchar_t* buf = conv_utf8_to_utf16(path);
int ret = _wrmdir(buf);
free(buf);
return ret;
}
int p_hide_directory__w32(const char *path) int p_hide_directory__w32(const char *path)
{ {
int error; int error;
wchar_t* buf = conv_utf8_to_utf16(path);
error = SetFileAttributes(path, FILE_ATTRIBUTE_HIDDEN) != 0 ? error = SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0 ?
GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */ GIT_SUCCESS : GIT_ERROR; /* MSDN states a "non zero" value indicates a success */
free(buf);
if (error < GIT_SUCCESS) if (error < GIT_SUCCESS)
error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path); error = git__throw(GIT_EOSERR, "Failed to hide directory '%s'", path);
...@@ -200,18 +305,30 @@ int p_hide_directory__w32(const char *path) ...@@ -200,18 +305,30 @@ int p_hide_directory__w32(const char *path)
char *p_realpath(const char *orig_path, char *buffer) char *p_realpath(const char *orig_path, char *buffer)
{ {
int ret, alloc = 0; int ret, alloc = 0;
wchar_t* orig_path_w = conv_utf8_to_utf16(orig_path);
wchar_t* buffer_w = (wchar_t*)git__malloc(GIT_PATH_MAX * sizeof(wchar_t));
if (buffer == NULL) { if (buffer == NULL) {
buffer = (char *)git__malloc(GIT_PATH_MAX); buffer = (char *)git__malloc(GIT_PATH_MAX);
alloc = 1; alloc = 1;
} }
ret = GetFullPathName(orig_path, GIT_PATH_MAX, buffer, NULL); ret = GetFullPathNameW(orig_path_w, GIT_PATH_MAX, buffer_w, NULL);
free(orig_path_w);
if (!ret || ret > GIT_PATH_MAX) { if (!ret || ret > GIT_PATH_MAX) {
free(buffer_w);
if (alloc) free(buffer); if (alloc) free(buffer);
return NULL; return NULL;
} }
if (!WideCharToMultiByte(CP_UTF8, 0, buffer_w, -1, buffer, GIT_PATH_MAX, NULL, NULL)) {
free(buffer_w);
if (alloc) free(buffer);
}
free(buffer_w);
git_path_mkposix(buffer); git_path_mkposix(buffer);
return buffer; return buffer;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "common.h" #include "common.h"
#include "fnmatch.h" #include "fnmatch.h"
#include "utf8-conv.h"
GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new)) GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new))
{ {
...@@ -20,8 +21,13 @@ GIT_INLINE(int) p_link(const char *GIT_UNUSED(old), const char *GIT_UNUSED(new)) ...@@ -20,8 +21,13 @@ 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)) GIT_INLINE(int) p_mkdir(const char *path, int GIT_UNUSED(mode))
{ {
wchar_t* buf = conv_utf8_to_utf16(path);
int ret = _wmkdir(buf);
GIT_UNUSED_ARG(mode) GIT_UNUSED_ARG(mode)
return mkdir(path);
free(buf);
return ret;
} }
extern int p_unlink(const char *path); extern int p_unlink(const char *path);
...@@ -33,5 +39,10 @@ extern int p_vsnprintf(char *buffer, size_t count, const char *format, va_list a ...@@ -33,5 +39,10 @@ extern int p_vsnprintf(char *buffer, size_t count, const char *format, va_list a
extern int p_snprintf(char *buffer, size_t count, const char *format, ...) GIT_FORMAT_PRINTF(3, 4); extern int p_snprintf(char *buffer, size_t count, const char *format, ...) GIT_FORMAT_PRINTF(3, 4);
extern int p_mkstemp(char *tmp_path); extern int p_mkstemp(char *tmp_path);
extern int p_setenv(const char* name, const char* value, int overwrite); extern int p_setenv(const char* name, const char* value, int overwrite);
extern int p_stat(const char* path, struct stat* buf);
extern int p_chdir(const char* path);
extern int p_chmod(const char* path, int mode);
extern int p_rmdir(const char* path);
#endif #endif
/*
* 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.
*/
#include "common.h"
#include "utf8-conv.h"
wchar_t* conv_utf8_to_utf16(const char* str)
{
wchar_t* ret;
int cb;
if (!str) {
return NULL;
}
cb = strlen(str) * sizeof(wchar_t);
if (cb == 0) {
ret = (wchar_t*)git__malloc(sizeof(wchar_t));
ret[0] = 0;
return ret;
}
/* Add space for null terminator */
cb += sizeof(wchar_t);
ret = (wchar_t*)git__malloc(cb);
if (MultiByteToWideChar(CP_UTF8, 0, str, -1, ret, cb) == 0) {
free(ret);
ret = NULL;
}
return ret;
}
char* conv_utf16_to_utf8(const wchar_t* str)
{
char* ret;
int cb;
if (!str) {
return NULL;
}
cb = wcslen(str) * sizeof(char);
if (cb == 0) {
ret = (char*)git__malloc(sizeof(char));
ret[0] = 0;
return ret;
}
/* Add space for null terminator */
cb += sizeof(char);
ret = (char*)git__malloc(cb);
if (WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, cb, NULL, NULL) == 0) {
free(ret);
ret = NULL;
}
return ret;
}
/*
* 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.
*/
#include <wchar.h>
#ifndef INCLUDE_git_utf8conv_h__
#define INCLUDE_git_utf8conv_h__
wchar_t* conv_utf8_to_utf16(const char* str);
char* conv_utf16_to_utf8(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