diff options
Diffstat (limited to 'src/win32')
| -rw-r--r-- | src/win32/dir.c | 38 | ||||
| -rw-r--r-- | src/win32/dir.h | 4 | ||||
| -rw-r--r-- | src/win32/error.c | 4 | ||||
| -rw-r--r-- | src/win32/findfile.c | 22 | ||||
| -rw-r--r-- | src/win32/mingw-compat.h | 5 | ||||
| -rw-r--r-- | src/win32/posix.h | 13 | ||||
| -rw-r--r-- | src/win32/posix_w32.c | 187 | ||||
| -rw-r--r-- | src/win32/precompiled.h | 3 | ||||
| -rw-r--r-- | src/win32/pthread.c | 115 | ||||
| -rw-r--r-- | src/win32/pthread.h | 34 | ||||
| -rw-r--r-- | src/win32/utf-conv.c | 8 | ||||
| -rw-r--r-- | src/win32/utf-conv.h | 31 | ||||
| -rw-r--r-- | src/win32/version.h | 25 |
13 files changed, 314 insertions, 175 deletions
diff --git a/src/win32/dir.c b/src/win32/dir.c index 8c51d8378..f7859b73f 100644 --- a/src/win32/dir.c +++ b/src/win32/dir.c @@ -5,8 +5,7 @@ * a Linking Exception. For full terms see the included COPYING file. */ #define GIT__WIN32_NO_WRAP_DIR -#include "dir.h" -#include "utf-conv.h" +#include "posix.h" static int init_filter(char *filter, size_t n, const char *dir) { @@ -25,36 +24,32 @@ static int init_filter(char *filter, size_t n, const char *dir) git__DIR *git__opendir(const char *dir) { - char filter[GIT_WIN_PATH]; - wchar_t filter_w[GIT_WIN_PATH]; + git_win32_path_as_utf8 filter; + git_win32_path filter_w; git__DIR *new = NULL; + size_t dirlen; if (!dir || !init_filter(filter, sizeof(filter), dir)) return NULL; - new = git__calloc(1, sizeof(*new)); + dirlen = strlen(dir); + + new = git__calloc(sizeof(*new) + dirlen + 1, 1); if (!new) return NULL; + memcpy(new->dir, dir, dirlen); - new->dir = git__strdup(dir); - if (!new->dir) - goto fail; - - git__utf8_to_16(filter_w, GIT_WIN_PATH, filter); + git_win32_path_from_c(filter_w, filter); new->h = FindFirstFileW(filter_w, &new->f); if (new->h == INVALID_HANDLE_VALUE) { giterr_set(GITERR_OS, "Could not open directory '%s'", dir); - goto fail; + git__free(new); + return NULL; } new->first = 1; return new; - -fail: - git__free(new->dir); - git__free(new); - return NULL; } int git__readdir_ext( @@ -80,7 +75,7 @@ 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); + git_win32_path_to_c(entry->d_name, d->f.cFileName); entry->d_ino = 0; *result = entry; @@ -101,8 +96,8 @@ struct git__dirent *git__readdir(git__DIR *d) void git__rewinddir(git__DIR *d) { - char filter[GIT_WIN_PATH]; - wchar_t filter_w[GIT_WIN_PATH]; + git_win32_path_as_utf8 filter; + git_win32_path filter_w; if (!d) return; @@ -116,7 +111,7 @@ void git__rewinddir(git__DIR *d) if (!init_filter(filter, sizeof(filter), d->dir)) return; - git__utf8_to_16(filter_w, GIT_WIN_PATH, filter); + git_win32_path_from_c(filter_w, filter); d->h = FindFirstFileW(filter_w, &d->f); if (d->h == INVALID_HANDLE_VALUE) @@ -134,8 +129,7 @@ int git__closedir(git__DIR *d) FindClose(d->h); d->h = INVALID_HANDLE_VALUE; } - git__free(d->dir); - d->dir = NULL; + git__free(d); return 0; } diff --git a/src/win32/dir.h b/src/win32/dir.h index 7696d468e..24d48f6ba 100644 --- a/src/win32/dir.h +++ b/src/win32/dir.h @@ -11,15 +11,15 @@ struct git__dirent { int d_ino; - char d_name[261]; + git_win32_path_as_utf8 d_name; }; typedef struct { HANDLE h; WIN32_FIND_DATAW f; struct git__dirent entry; - char *dir; int first; + char dir[GIT_FLEX_ARRAY]; } git__DIR; extern git__DIR *git__opendir(const char *); diff --git a/src/win32/error.c b/src/win32/error.c index 4a9a0631f..bc598ae32 100644 --- a/src/win32/error.c +++ b/src/win32/error.c @@ -12,7 +12,9 @@ # include <winhttp.h> #endif +#ifndef WC_ERR_INVALID_CHARS #define WC_ERR_INVALID_CHARS 0x80 +#endif char *git_win32_get_error_message(DWORD error_code) { @@ -45,7 +47,7 @@ char *git_win32_get_error_message(DWORD error_code) (LPWSTR)&lpMsgBuf, 0, NULL)) { /* Invalid code point check supported on Vista+ only */ - if (git_has_win32_version(6, 0)) + if (git_has_win32_version(6, 0, 0)) dwFlags = WC_ERR_INVALID_CHARS; else dwFlags = 0; diff --git a/src/win32/findfile.c b/src/win32/findfile.c index 5dd3de13d..a1c11fcfb 100644 --- a/src/win32/findfile.c +++ b/src/win32/findfile.c @@ -23,11 +23,11 @@ int git_win32__expand_path(struct git_win32__path *s_root, const wchar_t *templ) return s_root->len ? 0 : -1; } -static int win32_path_utf16_to_8(git_buf *path_utf8, const wchar_t *path_utf16) +static int win32_path_to_8(git_buf *path_utf8, const wchar_t *path) { char temp_utf8[GIT_PATH_MAX]; - git__utf16_to_8(temp_utf8, path_utf16); + git__utf16_to_8(temp_utf8, GIT_PATH_MAX, path); git_path_mkposix(temp_utf8); return git_buf_sets(path_utf8, temp_utf8); @@ -53,7 +53,7 @@ int git_win32__find_file( if (*filename == '/' || *filename == '\\') filename++; - git__utf8_to_16(file_utf16 + root->len - 1, alloc_len, filename); + git__utf8_to_16(file_utf16 + root->len - 1, alloc_len - root->len, filename); /* check access */ if (_waccess(file_utf16, F_OK) < 0) { @@ -61,7 +61,7 @@ int git_win32__find_file( return GIT_ENOTFOUND; } - win32_path_utf16_to_8(path, file_utf16); + win32_path_to_8(path, file_utf16); git__free(file_utf16); return 0; @@ -113,7 +113,7 @@ static int win32_find_git_in_path(git_buf *buf, const wchar_t *gitexe) /* replace "bin\\" or "cmd\\" with "etc\\" */ wcscpy(&root.path[root.len - 4], L"etc\\"); - win32_path_utf16_to_8(buf, root.path); + win32_path_to_8(buf, root.path); return 0; } } @@ -146,7 +146,7 @@ static int win32_find_git_in_registry( wcscat(path16.path, L"etc\\"); path16.len += 4; - win32_path_utf16_to_8(buf, path16.path); + win32_path_to_8(buf, path16.path); } RegCloseKey(hKey); @@ -156,7 +156,7 @@ static int win32_find_git_in_registry( } static int win32_find_existing_dirs( - git_buf *out, const wchar_t *tmpl[], char *temp[]) + git_buf *out, const wchar_t *tmpl[]) { struct git_win32__path path16; git_buf buf = GIT_BUF_INIT; @@ -168,7 +168,7 @@ static int win32_find_existing_dirs( path16.path[0] != L'%' && !_waccess(path16.path, F_OK)) { - win32_path_utf16_to_8(&buf, path16.path); + win32_path_to_8(&buf, path16.path); if (buf.size) git_buf_join(out, GIT_PATH_LIST_SEPARATOR, out->ptr, buf.ptr); @@ -209,7 +209,6 @@ int git_win32__find_system_dirs(git_buf *out) int git_win32__find_global_dirs(git_buf *out) { - char *temp[3]; static const wchar_t *global_tmpls[4] = { L"%HOME%\\", L"%HOMEDRIVE%%HOMEPATH%\\", @@ -217,12 +216,11 @@ int git_win32__find_global_dirs(git_buf *out) NULL, }; - return win32_find_existing_dirs(out, global_tmpls, temp); + return win32_find_existing_dirs(out, global_tmpls); } int git_win32__find_xdg_dirs(git_buf *out) { - char *temp[6]; static const wchar_t *global_tmpls[7] = { L"%XDG_CONFIG_HOME%\\git", L"%APPDATA%\\git", @@ -233,5 +231,5 @@ int git_win32__find_xdg_dirs(git_buf *out) NULL, }; - return win32_find_existing_dirs(out, global_tmpls, temp); + return win32_find_existing_dirs(out, global_tmpls); } diff --git a/src/win32/mingw-compat.h b/src/win32/mingw-compat.h index 7b97b48db..fe0abfb54 100644 --- a/src/win32/mingw-compat.h +++ b/src/win32/mingw-compat.h @@ -19,6 +19,11 @@ # define S_IFLNK _S_IFLNK # define S_ISLNK(m) (((m) & _S_IFMT) == _S_IFLNK) +GIT_INLINE(size_t) p_strnlen(const char *s, size_t maxlen) { + const char *end = memchr(s, 0, maxlen); + return end ? (size_t)(end - s) : maxlen; +} + #endif #endif /* INCLUDE_mingw_compat__ */ diff --git a/src/win32/posix.h b/src/win32/posix.h index c49c2175c..24cba23e0 100644 --- a/src/win32/posix.h +++ b/src/win32/posix.h @@ -8,7 +8,16 @@ #define INCLUDE_posix__w32_h__ #include "common.h" +#include "../posix.h" #include "utf-conv.h" +#include "dir.h" + +/* define some standard errnos that the runtime may be missing. for example, + * mingw lacks EAFNOSUPPORT. */ + +#ifndef EAFNOSUPPORT +# define EAFNOSUPPORT (INT_MAX-1) +#endif GIT_INLINE(int) p_link(const char *old, const char *new) { @@ -20,9 +29,9 @@ 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[GIT_WIN_PATH]; + git_win32_path buf; GIT_UNUSED(mode); - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path_from_c(buf, path); return _wmkdir(buf); } diff --git a/src/win32/posix_w32.c b/src/win32/posix_w32.c index f04974428..2f490529c 100644 --- a/src/win32/posix_w32.c +++ b/src/win32/posix_w32.c @@ -16,8 +16,8 @@ int p_unlink(const char *path) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path buf; + git_win32_path_from_c(buf, path); _wchmod(buf, 0666); return _wunlink(buf); } @@ -59,10 +59,11 @@ static int do_lstat( const char *file_name, struct stat *buf, int posix_enotdir) { WIN32_FILE_ATTRIBUTE_DATA fdata; - wchar_t fbuf[GIT_WIN_PATH], lastch; + git_win32_path fbuf; + wchar_t lastch; int flen; - flen = git__utf8_to_16(fbuf, GIT_WIN_PATH, file_name); + flen = git_win32_path_from_c(fbuf, file_name); /* truncate trailing slashes */ for (; flen > 0; --flen) { @@ -90,6 +91,9 @@ static int do_lstat( if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) fMode |= S_IFLNK; + if ((fMode & (S_IFDIR | S_IFLNK)) == (S_IFDIR | S_IFLNK)) // junction + fMode ^= S_IFLNK; + buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; @@ -105,10 +109,10 @@ static int do_lstat( * the length of the path pointed to, which we expect everywhere else */ if (S_ISLNK(fMode)) { - char target[GIT_WIN_PATH]; + git_win32_path_as_utf8 target; int readlink_result; - readlink_result = p_readlink(file_name, target, GIT_WIN_PATH); + readlink_result = p_readlink(file_name, target, sizeof(target)); if (readlink_result == -1) return -1; @@ -156,13 +160,22 @@ int p_lstat_posixly(const char *filename, struct stat *buf) return do_lstat(filename, buf, 1); } + +/* + * Parts of the The p_readlink function are heavily inspired by the php + * readlink function in link_win32.c + * + * Copyright (c) 1999 - 2012 The PHP Group. All rights reserved. + * + * For details of the PHP license see http://www.php.net/license/3_01.txt + */ int p_readlink(const char *link, char *target, size_t target_len) { typedef DWORD (WINAPI *fpath_func)(HANDLE, LPWSTR, DWORD, DWORD); static fpath_func pGetFinalPath = NULL; HANDLE hFile; DWORD dwRet; - wchar_t link_w[GIT_WIN_PATH]; + git_win32_path link_w; wchar_t* target_w; int error = 0; @@ -185,7 +198,7 @@ int p_readlink(const char *link, char *target, size_t target_len) } } - git__utf8_to_16(link_w, GIT_WIN_PATH, link); + git_win32_path_from_c(link_w, link); hFile = CreateFileW(link_w, // file to open GENERIC_READ, // open for reading @@ -251,10 +264,10 @@ int p_symlink(const char *old, const char *new) int p_open(const char *path, int flags, ...) { - wchar_t buf[GIT_WIN_PATH]; + git_win32_path buf; mode_t mode = 0; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path_from_c(buf, path); if (flags & O_CREAT) { va_list arg_list; @@ -269,8 +282,8 @@ int p_open(const char *path, int flags, ...) int p_creat(const char *path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path buf; + git_win32_path_from_c(buf, path); return _wopen(buf, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY, mode); } @@ -296,7 +309,7 @@ int p_getcwd(char *buffer_out, size_t size) int p_stat(const char* path, struct stat* buf) { - char target[GIT_WIN_PATH]; + git_win32_path_as_utf8 target; int error = 0; error = do_lstat(path, buf, 0); @@ -304,7 +317,7 @@ int p_stat(const char* path, struct stat* buf) /* We need not do this in a loop to unwind chains of symlinks since * p_readlink calls GetFinalPathNameByHandle which does it for us. */ if (error >= 0 && S_ISLNK(buf->st_mode) && - (error = p_readlink(path, target, GIT_WIN_PATH)) >= 0) + (error = p_readlink(path, target, sizeof(target))) >= 0) error = do_lstat(target, buf, 0); return error; @@ -312,23 +325,23 @@ int p_stat(const char* path, struct stat* buf) int p_chdir(const char* path) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path buf; + git_win32_path_from_c(buf, path); return _wchdir(buf); } int p_chmod(const char* path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path buf; + git_win32_path_from_c(buf, path); return _wchmod(buf, mode); } int p_rmdir(const char* path) { int error; - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path buf; + git_win32_path_from_c(buf, path); error = _wrmdir(buf); @@ -344,24 +357,24 @@ int p_rmdir(const char* path) int p_hide_directory__w32(const char *path) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path buf; + git_win32_path_from_c(buf, path); return (SetFileAttributesW(buf, FILE_ATTRIBUTE_HIDDEN) != 0) ? 0 : -1; } char *p_realpath(const char *orig_path, char *buffer) { int ret; - wchar_t orig_path_w[GIT_WIN_PATH]; - wchar_t buffer_w[GIT_WIN_PATH]; + git_win32_path orig_path_w; + git_win32_path buffer_w; - git__utf8_to_16(orig_path_w, GIT_WIN_PATH, orig_path); + git_win32_path_from_c(orig_path_w, orig_path); /* Implicitly use GetCurrentDirectory which can be a threading issue */ - ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH, buffer_w, NULL); + ret = GetFullPathNameW(orig_path_w, GIT_WIN_PATH_UTF16, buffer_w, NULL); /* According to MSDN, a return value equals to zero means a failure. */ - if (ret == 0 || ret > GIT_WIN_PATH) + if (ret == 0 || ret > GIT_WIN_PATH_UTF16) buffer = NULL; else if (GetFileAttributesW(buffer_w) == INVALID_FILE_ATTRIBUTES) { @@ -445,18 +458,18 @@ int p_setenv(const char* name, const char* value, int overwrite) int p_access(const char* path, mode_t mode) { - wchar_t buf[GIT_WIN_PATH]; - git__utf8_to_16(buf, GIT_WIN_PATH, path); + git_win32_path buf; + git_win32_path_from_c(buf, path); return _waccess(buf, mode); } int p_rename(const char *from, const char *to) { - wchar_t wfrom[GIT_WIN_PATH]; - wchar_t wto[GIT_WIN_PATH]; + git_win32_path wfrom; + git_win32_path wto; - git__utf8_to_16(wfrom, GIT_WIN_PATH, from); - git__utf8_to_16(wto, GIT_WIN_PATH, to); + git_win32_path_from_c(wfrom, from); + git_win32_path_from_c(wto, to); return MoveFileExW(wfrom, wto, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) ? 0 : -1; } @@ -505,94 +518,40 @@ p_gmtime_r (const time_t *timer, struct tm *result) return result; } -#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 -#else -#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL -#endif - -#ifndef _TIMEZONE_DEFINED -#define _TIMEZONE_DEFINED -struct timezone -{ - int tz_minuteswest; /* minutes W of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; -#endif - -int p_gettimeofday(struct timeval *tv, struct timezone *tz) +int p_inet_pton(int af, const char *src, void *dst) { - FILETIME ft; - unsigned __int64 tmpres = 0; - static int tzflag; - - if (NULL != tv) - { - GetSystemTimeAsFileTime(&ft); - - tmpres |= ft.dwHighDateTime; - tmpres <<= 32; - tmpres |= ft.dwLowDateTime; - - /*converting file time to unix epoch*/ - tmpres /= 10; /*convert into microseconds*/ - tmpres -= DELTA_EPOCH_IN_MICROSECS; - tv->tv_sec = (long)(tmpres / 1000000UL); - tv->tv_usec = (long)(tmpres % 1000000UL); - } + struct sockaddr_storage sin; + void *addr; + int sin_len = sizeof(struct sockaddr_storage), addr_len; + int error = 0; - if (NULL != tz) - { - if (!tzflag) - { - _tzset(); - tzflag++; - } - tz->tz_minuteswest = _timezone / 60; - tz->tz_dsttime = _daylight; + if (af == AF_INET) { + addr = &((struct sockaddr_in *)&sin)->sin_addr; + addr_len = sizeof(struct in_addr); + } else if (af == AF_INET6) { + addr = &((struct sockaddr_in6 *)&sin)->sin6_addr; + addr_len = sizeof(struct in6_addr); + } else { + errno = EAFNOSUPPORT; + return -1; } - return 0; -} - -int p_inet_pton(int af, const char* src, void* dst) -{ - union { - struct sockaddr_in6 sin6; - struct sockaddr_in sin; - } sa; - int srcsize; - - switch(af) - { - case AF_INET: - sa.sin.sin_family = AF_INET; - srcsize = (int)sizeof(sa.sin); - break; - case AF_INET6: - sa.sin6.sin6_family = AF_INET6; - srcsize = (int)sizeof(sa.sin6); - break; - default: - errno = WSAEPFNOSUPPORT; - return -1; + if ((error = WSAStringToAddressA((LPSTR)src, af, NULL, (LPSOCKADDR)&sin, &sin_len)) == 0) { + memcpy(dst, addr, addr_len); + return 1; } - if (WSAStringToAddress((LPSTR)src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0) - { - errno = WSAGetLastError(); + switch(WSAGetLastError()) { + case WSAEINVAL: + return 0; + case WSAEFAULT: + errno = ENOSPC; + return -1; + case WSA_NOT_ENOUGH_MEMORY: + errno = ENOMEM; return -1; } - switch(af) - { - case AF_INET: - memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr)); - break; - case AF_INET6: - memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr)); - break; - } - - return 1; + errno = EINVAL; + return -1; } diff --git a/src/win32/precompiled.h b/src/win32/precompiled.h index 5de7e6f34..cbfe98812 100644 --- a/src/win32/precompiled.h +++ b/src/win32/precompiled.h @@ -1,4 +1,5 @@ #include "git2.h" +#include "common.h" #include <assert.h> #include <errno.h> @@ -6,6 +7,8 @@ #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <fcntl.h> +#include <time.h> #include <sys/types.h> #include <sys/stat.h> diff --git a/src/win32/pthread.c b/src/win32/pthread.c index 2f263b3e0..d50ace695 100644 --- a/src/win32/pthread.c +++ b/src/win32/pthread.c @@ -127,9 +127,10 @@ int pthread_cond_signal(pthread_cond_t *cond) return 0; } -/* pthread_cond_broadcast is not implemented because doing so with just Win32 events - * is quite complicated, and no caller in libgit2 uses it yet. */ - +/* pthread_cond_broadcast is not implemented because doing so with just + * Win32 events is quite complicated, and no caller in libgit2 uses it + * yet. + */ int pthread_num_processors_np(void) { DWORD_PTR p, s; @@ -142,3 +143,111 @@ int pthread_num_processors_np(void) return n ? n : 1; } + +static HINSTANCE win32_kernel32_dll; + +typedef void (WINAPI *win32_srwlock_fn)(GIT_SRWLOCK *); + +static win32_srwlock_fn win32_srwlock_initialize; +static win32_srwlock_fn win32_srwlock_acquire_shared; +static win32_srwlock_fn win32_srwlock_release_shared; +static win32_srwlock_fn win32_srwlock_acquire_exclusive; +static win32_srwlock_fn win32_srwlock_release_exclusive; + +int pthread_rwlock_init( + pthread_rwlock_t *GIT_RESTRICT lock, + const pthread_rwlockattr_t *GIT_RESTRICT attr) +{ + (void)attr; + + if (win32_srwlock_initialize) + win32_srwlock_initialize(&lock->native.srwl); + else + InitializeCriticalSection(&lock->native.csec); + + return 0; +} + +int pthread_rwlock_rdlock(pthread_rwlock_t *lock) +{ + if (win32_srwlock_acquire_shared) + win32_srwlock_acquire_shared(&lock->native.srwl); + else + EnterCriticalSection(&lock->native.csec); + + return 0; +} + +int pthread_rwlock_rdunlock(pthread_rwlock_t *lock) +{ + if (win32_srwlock_release_shared) + win32_srwlock_release_shared(&lock->native.srwl); + else + LeaveCriticalSection(&lock->native.csec); + + return 0; +} + +int pthread_rwlock_wrlock(pthread_rwlock_t *lock) +{ + if (win32_srwlock_acquire_exclusive) + win32_srwlock_acquire_exclusive(&lock->native.srwl); + else + EnterCriticalSection(&lock->native.csec); + + return 0; +} + +int pthread_rwlock_wrunlock(pthread_rwlock_t *lock) +{ + if (win32_srwlock_release_exclusive) + win32_srwlock_release_exclusive(&lock->native.srwl); + else + LeaveCriticalSection(&lock->native.csec); + + return 0; +} + +int pthread_rwlock_destroy(pthread_rwlock_t *lock) +{ + if (!win32_srwlock_initialize) + DeleteCriticalSection(&lock->native.csec); + git__memzero(lock, sizeof(*lock)); + return 0; +} + + +int win32_pthread_initialize(void) +{ + if (win32_kernel32_dll) + return 0; + + win32_kernel32_dll = LoadLibrary("Kernel32.dll"); + if (!win32_kernel32_dll) { + giterr_set(GITERR_OS, "Could not load Kernel32.dll!"); + return -1; + } + + win32_srwlock_initialize = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "InitializeSRWLock"); + win32_srwlock_acquire_shared = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "AcquireSRWLockShared"); + win32_srwlock_release_shared = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockShared"); + win32_srwlock_acquire_exclusive = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "AcquireSRWLockExclusive"); + win32_srwlock_release_exclusive = (win32_srwlock_fn) + GetProcAddress(win32_kernel32_dll, "ReleaseSRWLockExclusive"); + + return 0; +} + +int win32_pthread_shutdown(void) +{ + if (win32_kernel32_dll) { + FreeLibrary(win32_kernel32_dll); + win32_kernel32_dll = NULL; + } + + return 0; +} diff --git a/src/win32/pthread.h b/src/win32/pthread.h index 8277ecf6e..2ba2ca552 100644 --- a/src/win32/pthread.h +++ b/src/win32/pthread.h @@ -19,22 +19,34 @@ typedef int pthread_mutexattr_t; typedef int pthread_condattr_t; typedef int pthread_attr_t; +typedef int pthread_rwlockattr_t; + typedef CRITICAL_SECTION pthread_mutex_t; typedef HANDLE pthread_t; typedef HANDLE pthread_cond_t; -#define PTHREAD_MUTEX_INITIALIZER {(void*)-1}; +typedef struct { void *Ptr; } GIT_SRWLOCK; + +typedef struct { + union { + GIT_SRWLOCK srwl; + CRITICAL_SECTION csec; + } native; +} pthread_rwlock_t; + +#define PTHREAD_MUTEX_INITIALIZER {(void*)-1} int pthread_create( - pthread_t *GIT_RESTRICT, - const pthread_attr_t *GIT_RESTRICT, + pthread_t *GIT_RESTRICT thread, + const pthread_attr_t *GIT_RESTRICT attr, void *(*start_routine)(void*), - void *__restrict); + void *GIT_RESTRICT arg); int pthread_join(pthread_t, void **); int pthread_mutex_init( - pthread_mutex_t *GIT_RESTRICT, const pthread_mutexattr_t *GIT_RESTRICT); + pthread_mutex_t *GIT_RESTRICT mutex, + const pthread_mutexattr_t *GIT_RESTRICT mutexattr); int pthread_mutex_destroy(pthread_mutex_t *); int pthread_mutex_lock(pthread_mutex_t *); int pthread_mutex_unlock(pthread_mutex_t *); @@ -47,4 +59,16 @@ int pthread_cond_signal(pthread_cond_t *); int pthread_num_processors_np(void); +int pthread_rwlock_init( + pthread_rwlock_t *GIT_RESTRICT lock, + const pthread_rwlockattr_t *GIT_RESTRICT attr); +int pthread_rwlock_rdlock(pthread_rwlock_t *); +int pthread_rwlock_rdunlock(pthread_rwlock_t *); +int pthread_rwlock_wrlock(pthread_rwlock_t *); +int pthread_rwlock_wrunlock(pthread_rwlock_t *); +int pthread_rwlock_destroy(pthread_rwlock_t *); + +extern int win32_pthread_initialize(void); +extern int win32_pthread_shutdown(void); + #endif diff --git a/src/win32/utf-conv.c b/src/win32/utf-conv.c index c06f3a8c2..d4dbfbab9 100644 --- a/src/win32/utf-conv.c +++ b/src/win32/utf-conv.c @@ -70,12 +70,12 @@ void git__utf8_to_16(wchar_t *dest, size_t length, const char *src) } #endif -int git__utf8_to_16(wchar_t *dest, size_t length, const char *src) +int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src) { - return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, (int)length); + return MultiByteToWideChar(CP_UTF8, 0, src, -1, dest, (int)dest_size); } -int git__utf16_to_8(char *out, const wchar_t *input) +int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src) { - return WideCharToMultiByte(CP_UTF8, 0, input, -1, out, GIT_WIN_PATH, NULL, NULL); + return WideCharToMultiByte(CP_UTF8, 0, src, -1, dest, (int)dest_size, NULL, NULL); } diff --git a/src/win32/utf-conv.h b/src/win32/utf-conv.h index 6cc9205f7..3af77580e 100644 --- a/src/win32/utf-conv.h +++ b/src/win32/utf-conv.h @@ -4,16 +4,35 @@ * 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_utfconv_h__ +#define INCLUDE_git_utfconv_h__ #include <wchar.h> +#include "common.h" -#ifndef INCLUDE_git_utfconv_h__ -#define INCLUDE_git_utfconv_h__ +/* Maximum characters in a Windows path plus one for NUL byte */ +#define GIT_WIN_PATH_UTF16 (260 + 1) -#define GIT_WIN_PATH (260 + 1) +/* Maximum bytes necessary to convert a full-length UTF16 path to UTF8 */ +#define GIT_WIN_PATH_UTF8 (260 * 4 + 1) -int git__utf8_to_16(wchar_t *dest, size_t length, const char *src); -int git__utf16_to_8(char *dest, const wchar_t *src); +typedef wchar_t git_win32_path[GIT_WIN_PATH_UTF16]; -#endif +typedef char git_win32_path_as_utf8[GIT_WIN_PATH_UTF8]; +/* dest_size is the size of dest in wchar_t's */ +int git__utf8_to_16(wchar_t * dest, size_t dest_size, const char *src); +/* dest_size is the size of dest in char's */ +int git__utf16_to_8(char *dest, size_t dest_size, const wchar_t *src); + +GIT_INLINE(int) git_win32_path_from_c(git_win32_path dest, const char *src) +{ + return git__utf8_to_16(dest, GIT_WIN_PATH_UTF16, src); +} + +GIT_INLINE(int) git_win32_path_to_c(git_win32_path_as_utf8 dest, const wchar_t *src) +{ + return git__utf16_to_8(dest, GIT_WIN_PATH_UTF8, src); +} + +#endif diff --git a/src/win32/version.h b/src/win32/version.h index 483962b57..79667697f 100644 --- a/src/win32/version.h +++ b/src/win32/version.h @@ -9,12 +9,29 @@ #include <windows.h> -GIT_INLINE(int) git_has_win32_version(int major, int minor) +GIT_INLINE(int) git_has_win32_version(int major, int minor, int service_pack) { - WORD wVersion = LOWORD(GetVersion()); + OSVERSIONINFOEX version_test = {0}; + DWORD version_test_mask; + DWORDLONG version_condition_mask = 0; + + version_test.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + version_test.dwMajorVersion = major; + version_test.dwMinorVersion = minor; + version_test.wServicePackMajor = (WORD)service_pack; + version_test.wServicePackMinor = 0; - return LOBYTE(wVersion) > major || - (LOBYTE(wVersion) == major && HIBYTE(wVersion) >= minor); + version_test_mask = (VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR | VER_SERVICEPACKMINOR); + + VER_SET_CONDITION(version_condition_mask, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_MINORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL); + VER_SET_CONDITION(version_condition_mask, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL); + + if (!VerifyVersionInfo(&version_test, version_test_mask, version_condition_mask)) + return 0; + + return 1; } #endif |
