11#include "../git-compat-util.h"
22#include "win32.h"
33#include <conio.h>
4+ #include <wchar.h>
45#include "../strbuf.h"
56#include "../run-command.h"
67
@@ -198,14 +199,16 @@ static int ask_yes_no_if_possible(const char *format, ...)
198199 }
199200}
200201
201- #undef unlink
202202int mingw_unlink (const char * pathname )
203203{
204204 int ret , tries = 0 ;
205+ wchar_t wpathname [MAX_PATH ];
206+ if (xutftowcs_path (wpathname , pathname ) < 0 )
207+ return -1 ;
205208
206209 /* read-only files cannot be removed */
207- chmod ( pathname , 0666 );
208- while ((ret = unlink ( pathname )) == -1 && tries < ARRAY_SIZE (delay )) {
210+ _wchmod ( wpathname , 0666 );
211+ while ((ret = _wunlink ( wpathname )) == -1 && tries < ARRAY_SIZE (delay )) {
209212 if (!is_file_in_use_error (GetLastError ()))
210213 break ;
211214 /*
@@ -221,45 +224,45 @@ int mingw_unlink(const char *pathname)
221224 while (ret == -1 && is_file_in_use_error (GetLastError ()) &&
222225 ask_yes_no_if_possible ("Unlink of file '%s' failed. "
223226 "Should I try again?" , pathname ))
224- ret = unlink ( pathname );
227+ ret = _wunlink ( wpathname );
225228 return ret ;
226229}
227230
228- static int is_dir_empty (const char * path )
231+ static int is_dir_empty (const wchar_t * wpath )
229232{
230- struct strbuf buf = STRBUF_INIT ;
231- WIN32_FIND_DATAA findbuf ;
233+ WIN32_FIND_DATAW findbuf ;
232234 HANDLE handle ;
233-
234- strbuf_addf ( & buf , "%s\\*" , path );
235- handle = FindFirstFileA ( buf . buf , & findbuf );
236- if ( handle == INVALID_HANDLE_VALUE ) {
237- strbuf_release ( & buf );
235+ wchar_t wbuf [ MAX_PATH + 2 ];
236+ wcscpy ( wbuf , wpath );
237+ wcscat ( wbuf , L"\\*" );
238+ handle = FindFirstFileW ( wbuf , & findbuf );
239+ if ( handle == INVALID_HANDLE_VALUE )
238240 return GetLastError () == ERROR_NO_MORE_FILES ;
239- }
240241
241- while (!strcmp (findbuf .cFileName , "." ) ||
242- !strcmp (findbuf .cFileName , ".." ))
243- if (!FindNextFile (handle , & findbuf )) {
244- strbuf_release (& buf );
245- return GetLastError () == ERROR_NO_MORE_FILES ;
242+ while (!wcscmp (findbuf .cFileName , L"." ) ||
243+ !wcscmp (findbuf .cFileName , L".." ))
244+ if (!FindNextFileW (handle , & findbuf )) {
245+ DWORD err = GetLastError ();
246+ FindClose (handle );
247+ return err == ERROR_NO_MORE_FILES ;
246248 }
247249 FindClose (handle );
248- strbuf_release (& buf );
249250 return 0 ;
250251}
251252
252- #undef rmdir
253253int mingw_rmdir (const char * pathname )
254254{
255255 int ret , tries = 0 ;
256+ wchar_t wpathname [MAX_PATH ];
257+ if (xutftowcs_path (wpathname , pathname ) < 0 )
258+ return -1 ;
256259
257- while ((ret = rmdir ( pathname )) == -1 && tries < ARRAY_SIZE (delay )) {
260+ while ((ret = _wrmdir ( wpathname )) == -1 && tries < ARRAY_SIZE (delay )) {
258261 if (!is_file_in_use_error (GetLastError ()))
259262 errno = err_win_to_posix (GetLastError ());
260263 if (errno != EACCES )
261264 break ;
262- if (!is_dir_empty (pathname )) {
265+ if (!is_dir_empty (wpathname )) {
263266 errno = ENOTEMPTY ;
264267 break ;
265268 }
@@ -276,16 +279,26 @@ int mingw_rmdir(const char *pathname)
276279 while (ret == -1 && errno == EACCES && is_file_in_use_error (GetLastError ()) &&
277280 ask_yes_no_if_possible ("Deletion of directory '%s' failed. "
278281 "Should I try again?" , pathname ))
279- ret = rmdir (pathname );
282+ ret = _wrmdir (wpathname );
283+ return ret ;
284+ }
285+
286+ int mingw_mkdir (const char * path , int mode )
287+ {
288+ int ret ;
289+ wchar_t wpath [MAX_PATH ];
290+ if (xutftowcs_path (wpath , path ) < 0 )
291+ return -1 ;
292+ ret = _wmkdir (wpath );
280293 return ret ;
281294}
282295
283- #undef open
284296int mingw_open (const char * filename , int oflags , ...)
285297{
286298 va_list args ;
287299 unsigned mode ;
288300 int fd ;
301+ wchar_t wfilename [MAX_PATH ];
289302
290303 va_start (args , oflags );
291304 mode = va_arg (args , int );
@@ -294,10 +307,12 @@ int mingw_open (const char *filename, int oflags, ...)
294307 if (filename && !strcmp (filename , "/dev/null" ))
295308 filename = "nul" ;
296309
297- fd = open (filename , oflags , mode );
310+ if (xutftowcs_path (wfilename , filename ) < 0 )
311+ return -1 ;
312+ fd = _wopen (wfilename , oflags , mode );
298313
299314 if (fd < 0 && (oflags & O_CREAT ) && errno == EACCES ) {
300- DWORD attrs = GetFileAttributes ( filename );
315+ DWORD attrs = GetFileAttributesW ( wfilename );
301316 if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY ))
302317 errno = EISDIR ;
303318 }
@@ -332,17 +347,28 @@ int mingw_fgetc(FILE *stream)
332347#undef fopen
333348FILE * mingw_fopen (const char * filename , const char * otype )
334349{
350+ FILE * file ;
351+ wchar_t wfilename [MAX_PATH ], wotype [4 ];
335352 if (filename && !strcmp (filename , "/dev/null" ))
336353 filename = "nul" ;
337- return fopen (filename , otype );
354+ if (xutftowcs_path (wfilename , filename ) < 0 ||
355+ xutftowcs (wotype , otype , ARRAY_SIZE (wotype )) < 0 )
356+ return NULL ;
357+ file = _wfopen (wfilename , wotype );
358+ return file ;
338359}
339360
340- #undef freopen
341361FILE * mingw_freopen (const char * filename , const char * otype , FILE * stream )
342362{
363+ FILE * file ;
364+ wchar_t wfilename [MAX_PATH ], wotype [4 ];
343365 if (filename && !strcmp (filename , "/dev/null" ))
344366 filename = "nul" ;
345- return freopen (filename , otype , stream );
367+ if (xutftowcs_path (wfilename , filename ) < 0 ||
368+ xutftowcs (wotype , otype , ARRAY_SIZE (wotype )) < 0 )
369+ return NULL ;
370+ file = _wfreopen (wfilename , wotype , stream );
371+ return file ;
346372}
347373
348374#undef fflush
@@ -367,6 +393,31 @@ int mingw_fflush(FILE *stream)
367393 return ret ;
368394}
369395
396+ int mingw_access (const char * filename , int mode )
397+ {
398+ wchar_t wfilename [MAX_PATH ];
399+ if (xutftowcs_path (wfilename , filename ) < 0 )
400+ return -1 ;
401+ /* X_OK is not supported by the MSVCRT version */
402+ return _waccess (wfilename , mode & ~X_OK );
403+ }
404+
405+ int mingw_chdir (const char * dirname )
406+ {
407+ wchar_t wdirname [MAX_PATH ];
408+ if (xutftowcs_path (wdirname , dirname ) < 0 )
409+ return -1 ;
410+ return _wchdir (wdirname );
411+ }
412+
413+ int mingw_chmod (const char * filename , int mode )
414+ {
415+ wchar_t wfilename [MAX_PATH ];
416+ if (xutftowcs_path (wfilename , filename ) < 0 )
417+ return -1 ;
418+ return _wchmod (wfilename , mode );
419+ }
420+
370421/*
371422 * The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
372423 * Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
@@ -392,10 +443,12 @@ static inline time_t filetime_to_time_t(const FILETIME *ft)
392443 */
393444static int do_lstat (int follow , const char * file_name , struct stat * buf )
394445{
395- int err ;
396446 WIN32_FILE_ATTRIBUTE_DATA fdata ;
447+ wchar_t wfilename [MAX_PATH ];
448+ if (xutftowcs_path (wfilename , file_name ) < 0 )
449+ return -1 ;
397450
398- if (!( err = get_file_attr ( file_name , & fdata ) )) {
451+ if (GetFileAttributesExW ( wfilename , GetFileExInfoStandard , & fdata )) {
399452 buf -> st_ino = 0 ;
400453 buf -> st_gid = 0 ;
401454 buf -> st_uid = 0 ;
@@ -408,8 +461,8 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
408461 buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
409462 buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
410463 if (fdata .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) {
411- WIN32_FIND_DATAA findbuf ;
412- HANDLE handle = FindFirstFileA ( file_name , & findbuf );
464+ WIN32_FIND_DATAW findbuf ;
465+ HANDLE handle = FindFirstFileW ( wfilename , & findbuf );
413466 if (handle != INVALID_HANDLE_VALUE ) {
414467 if ((findbuf .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) &&
415468 (findbuf .dwReserved0 == IO_REPARSE_TAG_SYMLINK )) {
@@ -428,7 +481,23 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
428481 }
429482 return 0 ;
430483 }
431- errno = err ;
484+ switch (GetLastError ()) {
485+ case ERROR_ACCESS_DENIED :
486+ case ERROR_SHARING_VIOLATION :
487+ case ERROR_LOCK_VIOLATION :
488+ case ERROR_SHARING_BUFFER_EXCEEDED :
489+ errno = EACCES ;
490+ break ;
491+ case ERROR_BUFFER_OVERFLOW :
492+ errno = ENAMETOOLONG ;
493+ break ;
494+ case ERROR_NOT_ENOUGH_MEMORY :
495+ errno = ENOMEM ;
496+ break ;
497+ default :
498+ errno = ENOENT ;
499+ break ;
500+ }
432501 return -1 ;
433502}
434503
@@ -516,16 +585,20 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
516585{
517586 FILETIME mft , aft ;
518587 int fh , rc ;
588+ DWORD attrs ;
589+ wchar_t wfilename [MAX_PATH ];
590+ if (xutftowcs_path (wfilename , file_name ) < 0 )
591+ return -1 ;
519592
520593 /* must have write permission */
521- DWORD attrs = GetFileAttributes ( file_name );
594+ attrs = GetFileAttributesW ( wfilename );
522595 if (attrs != INVALID_FILE_ATTRIBUTES &&
523596 (attrs & FILE_ATTRIBUTE_READONLY )) {
524597 /* ignore errors here; open() will report them */
525- SetFileAttributes ( file_name , attrs & ~FILE_ATTRIBUTE_READONLY );
598+ SetFileAttributesW ( wfilename , attrs & ~FILE_ATTRIBUTE_READONLY );
526599 }
527600
528- if ((fh = open ( file_name , O_RDWR | O_BINARY )) < 0 ) {
601+ if ((fh = _wopen ( wfilename , O_RDWR | O_BINARY )) < 0 ) {
529602 rc = -1 ;
530603 goto revert_attrs ;
531604 }
@@ -548,7 +621,7 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
548621 if (attrs != INVALID_FILE_ATTRIBUTES &&
549622 (attrs & FILE_ATTRIBUTE_READONLY )) {
550623 /* ignore errors again */
551- SetFileAttributes ( file_name , attrs );
624+ SetFileAttributesW ( wfilename , attrs );
552625 }
553626 return rc ;
554627}
@@ -559,6 +632,18 @@ unsigned int sleep (unsigned int seconds)
559632 return 0 ;
560633}
561634
635+ char * mingw_mktemp (char * template )
636+ {
637+ wchar_t wtemplate [MAX_PATH ];
638+ if (xutftowcs_path (wtemplate , template ) < 0 )
639+ return NULL ;
640+ if (!_wmktemp (wtemplate ))
641+ return NULL ;
642+ if (xwcstoutf (template , wtemplate , strlen (template ) + 1 ) < 0 )
643+ return NULL ;
644+ return template ;
645+ }
646+
562647int mkstemp (char * template )
563648{
564649 char * filename = mktemp (template );
@@ -617,17 +702,18 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
617702 return result ;
618703}
619704
620- #undef getcwd
621705char * mingw_getcwd (char * pointer , int len )
622706{
623707 int i ;
624- char * ret = getcwd (pointer , len );
625- if (!ret )
626- return ret ;
708+ wchar_t wpointer [MAX_PATH ];
709+ if (!_wgetcwd (wpointer , ARRAY_SIZE (wpointer )))
710+ return NULL ;
711+ if (xwcstoutf (pointer , wpointer , len ) < 0 )
712+ return NULL ;
627713 for (i = 0 ; pointer [i ]; i ++ )
628714 if (pointer [i ] == '\\' )
629715 pointer [i ] = '/' ;
630- return ret ;
716+ return pointer ;
631717}
632718
633719/*
@@ -1485,33 +1571,36 @@ int mingw_rename(const char *pold, const char *pnew)
14851571{
14861572 DWORD attrs , gle ;
14871573 int tries = 0 ;
1574+ wchar_t wpold [MAX_PATH ], wpnew [MAX_PATH ];
1575+ if (xutftowcs_path (wpold , pold ) < 0 || xutftowcs_path (wpnew , pnew ) < 0 )
1576+ return -1 ;
14881577
14891578 /*
14901579 * Try native rename() first to get errno right.
14911580 * It is based on MoveFile(), which cannot overwrite existing files.
14921581 */
1493- if (!rename ( pold , pnew ))
1582+ if (!_wrename ( wpold , wpnew ))
14941583 return 0 ;
14951584 if (errno != EEXIST )
14961585 return -1 ;
14971586repeat :
1498- if (MoveFileEx ( pold , pnew , MOVEFILE_REPLACE_EXISTING ))
1587+ if (MoveFileExW ( wpold , wpnew , MOVEFILE_REPLACE_EXISTING ))
14991588 return 0 ;
15001589 /* TODO: translate more errors */
15011590 gle = GetLastError ();
15021591 if (gle == ERROR_ACCESS_DENIED &&
1503- (attrs = GetFileAttributes ( pnew )) != INVALID_FILE_ATTRIBUTES ) {
1592+ (attrs = GetFileAttributesW ( wpnew )) != INVALID_FILE_ATTRIBUTES ) {
15041593 if (attrs & FILE_ATTRIBUTE_DIRECTORY ) {
15051594 errno = EISDIR ;
15061595 return -1 ;
15071596 }
15081597 if ((attrs & FILE_ATTRIBUTE_READONLY ) &&
1509- SetFileAttributes ( pnew , attrs & ~FILE_ATTRIBUTE_READONLY )) {
1510- if (MoveFileEx ( pold , pnew , MOVEFILE_REPLACE_EXISTING ))
1598+ SetFileAttributesW ( wpnew , attrs & ~FILE_ATTRIBUTE_READONLY )) {
1599+ if (MoveFileExW ( wpold , wpnew , MOVEFILE_REPLACE_EXISTING ))
15111600 return 0 ;
15121601 gle = GetLastError ();
15131602 /* revert file attributes on failure */
1514- SetFileAttributes ( pnew , attrs );
1603+ SetFileAttributesW ( wpnew , attrs );
15151604 }
15161605 }
15171606 if (tries < ARRAY_SIZE (delay ) && gle == ERROR_ACCESS_DENIED ) {
@@ -1757,19 +1846,24 @@ void mingw_open_html(const char *unixpath)
17571846
17581847int link (const char * oldpath , const char * newpath )
17591848{
1760- typedef BOOL (WINAPI * T )(const char * , const char * , LPSECURITY_ATTRIBUTES );
1849+ typedef BOOL (WINAPI * T )(LPCWSTR , LPCWSTR , LPSECURITY_ATTRIBUTES );
17611850 static T create_hard_link = NULL ;
1851+ wchar_t woldpath [MAX_PATH ], wnewpath [MAX_PATH ];
1852+ if (xutftowcs_path (woldpath , oldpath ) < 0 ||
1853+ xutftowcs_path (wnewpath , newpath ) < 0 )
1854+ return -1 ;
1855+
17621856 if (!create_hard_link ) {
17631857 create_hard_link = (T ) GetProcAddress (
1764- GetModuleHandle ("kernel32.dll" ), "CreateHardLinkA " );
1858+ GetModuleHandle ("kernel32.dll" ), "CreateHardLinkW " );
17651859 if (!create_hard_link )
17661860 create_hard_link = (T )- 1 ;
17671861 }
17681862 if (create_hard_link == (T )- 1 ) {
17691863 errno = ENOSYS ;
17701864 return -1 ;
17711865 }
1772- if (!create_hard_link (newpath , oldpath , NULL )) {
1866+ if (!create_hard_link (wnewpath , woldpath , NULL )) {
17731867 errno = err_win_to_posix (GetLastError ());
17741868 return -1 ;
17751869 }
0 commit comments