Index: src/file.c ================================================================== --- src/file.c +++ src/file.c @@ -27,10 +27,14 @@ #include #include #include #include #include "file.h" +#if defined(_WIN32) +#include +#endif + /* ** On Windows, include the Platform SDK header file. */ #ifdef _WIN32 @@ -68,12 +72,12 @@ }else{ return stat(zFilename, buf); } #else int rc = 0; - char *zMbcs = fossil_utf8_to_mbcs(zFilename); - rc = stat(zMbcs, buf); + wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename); + rc = _wstati64(zMbcs, buf); fossil_mbcs_free(zMbcs); return rc; #endif } @@ -298,13 +302,17 @@ /* ** Wrapper around the access() system call. */ int file_access(const char *zFilename, int flags){ - char *zMbcs = fossil_utf8_to_mbcs(zFilename); - int rc = access(zMbcs, flags); +#ifdef _WIN32 + wchar_t *zMbcs = fossil_utf8_to_unicode(zFilename); + int rc = _waccess(zMbcs, flags); fossil_mbcs_free(zMbcs); +#else + int rc = access(zFilename, flags); +#endif return rc; } /* ** Find an unused filename similar to zBase with zSuffix appended. @@ -389,13 +397,17 @@ /* ** Delete a file. */ void file_delete(const char *zFilename){ - char *z = fossil_utf8_to_mbcs(zFilename); - unlink(z); +#ifdef _WIN32 + wchar_t *z = fossil_utf8_to_unicode(zFilename); + _wunlink(z); fossil_mbcs_free(z); +#else + unlink(zFilename); +#endif } /* ** Create the directory named in the argument, if it does not already ** exist. If forceFlag is 1, delete any prior non-directory object @@ -410,12 +422,12 @@ file_delete(zName); } if( rc!=1 ){ #if defined(_WIN32) int rc; - char *zMbcs = fossil_utf8_to_mbcs(zName); - rc = mkdir(zMbcs); + wchar_t *zMbcs = fossil_utf8_to_unicode(zName); + rc = _wmkdir(zMbcs); fossil_mbcs_free(zMbcs); return rc; #else return mkdir(zName, 0755); #endif @@ -561,24 +573,24 @@ } /* ** Get the current working directory. ** -** On windows, the name is converted from MBCS to UTF8 and all '\\' +** On windows, the name is converted from unicode to UTF8 and all '\\' ** characters are converted to '/'. No conversions are needed on ** unix. */ void file_getcwd(char *zBuf, int nBuf){ #ifdef _WIN32 char *zPwdUtf8; int nPwd; int i; - char zPwd[2000]; - if( getcwd(zPwd, sizeof(zPwd)-1)==0 ){ + wchar_t zPwd[2000]; + if( _wgetcwd(zPwd, sizeof(zPwd)-1)==0 ){ fossil_fatal("cannot find the current working directory."); } - zPwdUtf8 = fossil_mbcs_to_utf8(zPwd); + zPwdUtf8 = fossil_unicode_to_utf8(zPwd); nPwd = strlen(zPwdUtf8); if( nPwd > nBuf-1 ){ fossil_fatal("pwd too big: max %d\n", nBuf-1); } for(i=0; zPwdUtf8[i]; i++) if( zPwdUtf8[i]=='\\' ) zPwdUtf8[i] = '/'; @@ -928,14 +940,14 @@ unsigned int i, j; const char *zDir = "."; int cnt = 0; #if defined(_WIN32) - char zTmpPath[MAX_PATH]; + wchar_t zTmpPath[MAX_PATH]; - if( GetTempPath(sizeof(zTmpPath), zTmpPath) ){ - azDirs[0] = zTmpPath; + if( GetTempPathW(MAX_PATH, zTmpPath) ){ + azDirs[0] = fossil_unicode_to_utf8(zTmpPath); } azDirs[1] = fossil_getenv("TEMP"); azDirs[2] = fossil_getenv("TMP"); #endif @@ -1014,10 +1026,29 @@ return sqlite3_win32_mbcs_to_utf8(zMbcs); #else return (char*)zMbcs; /* No-op on unix */ #endif } + +/* +** Translate Unicode to UTF8. Return a pointer to the translated text. +** Call fossil_mbcs_free() to deallocate any memory used to store the +** returned pointer when done. +*/ +char *fossil_unicode_to_utf8(const void *zUnicode){ +#ifdef _WIN32 + int nByte = WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, 0, 0, 0, 0); + char *zUtf = sqlite3_malloc( nByte ); + if( zUtf==0 ){ + return 0; + } + WideCharToMultiByte(CP_UTF8, 0, zUnicode, -1, zUtf, nByte, 0, 0); + return zUtf; +#else + return (char *)zUnicode; /* No-op on unix */ +#endif +} /* ** Translate UTF8 to MBCS for use in system calls. Return a pointer to the ** translated text.. Call fossil_mbcs_free() to deallocate any memory ** used to store the returned pointer when done. @@ -1028,18 +1059,41 @@ return sqlite3_win32_utf8_to_mbcs(zUtf8); #else return (char*)zUtf8; /* No-op on unix */ #endif } + +/* +** Translate UTF8 to unicode for use in system calls. Return a pointer to the +** translated text.. Call fossil_mbcs_free() to deallocate any memory +** used to store the returned pointer when done. +*/ +void *fossil_utf8_to_unicode(const char *zUtf8){ +#ifdef _WIN32 + int nByte = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); + wchar_t *zUnicode = sqlite3_malloc( nByte * 2 ); + if( zUnicode==0 ){ + return 0; + } + MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nByte); + return zUnicode; +#else + return (void *)zUtf8; /* No-op on unix */ +#endif +} /* ** Return the value of an environment variable as UTF8. */ char *fossil_getenv(const char *zName){ - char *zValue = getenv(zName); #ifdef _WIN32 - if( zValue ) zValue = fossil_mbcs_to_utf8(zValue); + wchar_t *uName = fossil_utf8_to_unicode(zName); + void *zValue = _wgetenv(uName); + fossil_mbcs_free(uName); + if( zValue ) zValue = fossil_unicode_to_utf8(zValue); +#else + char *zValue = getenv(zName); #endif return zValue; } /* @@ -1085,11 +1139,11 @@ /* ** Translate MBCS to UTF8. Return a pointer. Call fossil_mbcs_free() ** to deallocate any memory used to store the returned pointer when done. */ -void fossil_mbcs_free(char *zOld){ +void fossil_mbcs_free(void *zOld){ #ifdef _WIN32 extern void sqlite3_free(void*); sqlite3_free(zOld); #else /* No-op on unix */ @@ -1098,10 +1152,16 @@ /* ** Like fopen() but always takes a UTF8 argument. */ FILE *fossil_fopen(const char *zName, const char *zMode){ - char *zMbcs = fossil_utf8_to_mbcs(zName); - FILE *f = fopen(zMbcs, zMode); - fossil_mbcs_free(zMbcs); +#ifdef _WIN32 + wchar_t *uMode = fossil_utf8_to_unicode(zMode); + wchar_t *uName = fossil_utf8_to_unicode(zName); + FILE *f = _wfopen(uName, uMode); + fossil_mbcs_free(uName); + fossil_mbcs_free(uMode); +#else + FILE *f = fopen(zName, zMode); +#endif return f; } Index: src/rebuild.c ================================================================== --- src/rebuild.c +++ src/rebuild.c @@ -21,10 +21,19 @@ #include "rebuild.h" #include #include #include +#ifndef _WIN32 +#define _WDIR DIR +#define _wdirent dirent +#define _wopendir opendir +#define _wreaddir readdir +#define _wclosedir closedir +#define wchar_t char +#endif + /* ** Make changes to the stable part of the schema (the part that is not ** simply deleted and reconstructed on a rebuild) to bring the schema ** up to the latest. */ @@ -818,28 +827,28 @@ /* ** Recursively read all files from the directory zPath and install ** every file read as a new artifact in the repository. */ void recon_read_dir(char *zPath){ - DIR *d; - struct dirent *pEntry; + _WDIR *d; + struct _wdirent *pEntry; Blob aContent; /* content of the just read artifact */ static int nFileRead = 0; - char *zMbcsPath; + wchar_t *zMbcsPath; char *zUtf8Name; - zMbcsPath = fossil_utf8_to_mbcs(zPath); - d = opendir(zMbcsPath); + zMbcsPath = fossil_utf8_to_unicode(zPath); + d = _wopendir(zMbcsPath); if( d ){ - while( (pEntry=readdir(d))!=0 ){ + while( (pEntry=_wreaddir(d))!=0 ){ Blob path; char *zSubpath; if( pEntry->d_name[0]=='.' ){ continue; } - zUtf8Name = fossil_mbcs_to_utf8(pEntry->d_name); + zUtf8Name = fossil_unicode_to_utf8(pEntry->d_name); zSubpath = mprintf("%s/%s", zPath, zUtf8Name); fossil_mbcs_free(zUtf8Name); if( file_isdir(zSubpath)==1 ){ recon_read_dir(zSubpath); } @@ -854,11 +863,11 @@ blob_reset(&aContent); free(zSubpath); fossil_print("\r%d", ++nFileRead); fflush(stdout); } - closedir(d); + _wclosedir(d); }else { fossil_panic("encountered error %d while trying to open \"%s\".", errno, g.argv[3]); } fossil_mbcs_free(zMbcsPath); Index: src/vfile.c ================================================================== --- src/vfile.c +++ src/vfile.c @@ -25,10 +25,19 @@ #include "dirent.h" #else #include #endif +#ifndef _WIN32 +#define _WDIR DIR +#define _wdirent dirent +#define _wopendir opendir +#define _wreaddir readdir +#define _wclosedir closedir +#define wchar_t char +#endif + /* ** The input is guaranteed to be a 40-character well-formed UUID. ** Find its rid. */ int fast_uuid_to_rid(const char *zUuid){ @@ -381,18 +390,18 @@ ** Any files or directories that match the glob pattern pIgnore are ** excluded from the scan. Name matching occurs after the first ** nPrefix characters are elided from the filename. */ void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){ - DIR *d; + _WDIR *d; int origSize; const char *zDir; - struct dirent *pEntry; + struct _wdirent *pEntry; int skipAll = 0; static Stmt ins; static int depth = 0; - char *zMbcs; + wchar_t *zMbcs; origSize = blob_size(pPath); if( pIgnore ){ blob_appendf(pPath, "/"); if( glob_match(pIgnore, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1; @@ -407,22 +416,22 @@ ); } depth++; zDir = blob_str(pPath); - zMbcs = fossil_utf8_to_mbcs(zDir); - d = opendir(zMbcs); + zMbcs = fossil_utf8_to_unicode(zDir); + d = _wopendir(zMbcs); if( d ){ - while( (pEntry=readdir(d))!=0 ){ + while( (pEntry=_wreaddir(d))!=0 ){ char *zPath; char *zUtf8; if( pEntry->d_name[0]=='.' ){ if( !allFlag ) continue; if( pEntry->d_name[1]==0 ) continue; if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue; } - zUtf8 = fossil_mbcs_to_utf8(pEntry->d_name); + zUtf8 = fossil_unicode_to_utf8(pEntry->d_name); blob_appendf(pPath, "/%s", zUtf8); fossil_mbcs_free(zUtf8); zPath = blob_str(pPath); if( glob_match(pIgnore, &zPath[nPrefix+1]) ){ /* do nothing */ @@ -435,11 +444,11 @@ db_step(&ins); db_reset(&ins); } blob_resize(pPath, origSize); } - closedir(d); + _wclosedir(d); } fossil_mbcs_free(zMbcs); depth--; if( depth==0 ){