1
1
#include "../git-compat-util.h"
2
2
#include "win32.h"
3
3
#include <conio.h>
4
+ #include <wchar.h>
4
5
#include "../strbuf.h"
5
6
#include "../run-command.h"
6
7
@@ -198,14 +199,16 @@ static int ask_yes_no_if_possible(const char *format, ...)
198
199
}
199
200
}
200
201
201
- #undef unlink
202
202
int mingw_unlink (const char * pathname )
203
203
{
204
204
int ret , tries = 0 ;
205
+ wchar_t wpathname [MAX_PATH ];
206
+ if (xutftowcs_path (wpathname , pathname ) < 0 )
207
+ return -1 ;
205
208
206
209
/* 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 )) {
209
212
if (!is_file_in_use_error (GetLastError ()))
210
213
break ;
211
214
/*
@@ -221,45 +224,42 @@ int mingw_unlink(const char *pathname)
221
224
while (ret == -1 && is_file_in_use_error (GetLastError ()) &&
222
225
ask_yes_no_if_possible ("Unlink of file '%s' failed. "
223
226
"Should I try again?" , pathname ))
224
- ret = unlink ( pathname );
227
+ ret = _wunlink ( wpathname );
225
228
return ret ;
226
229
}
227
230
228
- static int is_dir_empty (const char * path )
231
+ static int is_dir_empty (const wchar_t * wpath )
229
232
{
230
- struct strbuf buf = STRBUF_INIT ;
231
- WIN32_FIND_DATAA findbuf ;
233
+ WIN32_FIND_DATAW findbuf ;
232
234
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 )
238
240
return GetLastError () == ERROR_NO_MORE_FILES ;
239
- }
240
241
241
- while (!strcmp (findbuf .cFileName , "." ) ||
242
- !strcmp (findbuf .cFileName , ".." ))
243
- if (!FindNextFile (handle , & findbuf )) {
244
- strbuf_release (& buf );
242
+ while (!wcscmp (findbuf .cFileName , L"." ) ||
243
+ !wcscmp (findbuf .cFileName , L".." ))
244
+ if (!FindNextFileW (handle , & findbuf ))
245
245
return GetLastError () == ERROR_NO_MORE_FILES ;
246
- }
247
246
FindClose (handle );
248
- strbuf_release (& buf );
249
247
return 0 ;
250
248
}
251
249
252
- #undef rmdir
253
250
int mingw_rmdir (const char * pathname )
254
251
{
255
252
int ret , tries = 0 ;
253
+ wchar_t wpathname [MAX_PATH ];
254
+ if (xutftowcs_path (wpathname , pathname ) < 0 )
255
+ return -1 ;
256
256
257
- while ((ret = rmdir ( pathname )) == -1 && tries < ARRAY_SIZE (delay )) {
257
+ while ((ret = _wrmdir ( wpathname )) == -1 && tries < ARRAY_SIZE (delay )) {
258
258
if (!is_file_in_use_error (GetLastError ()))
259
259
errno = err_win_to_posix (GetLastError ());
260
260
if (errno != EACCES )
261
261
break ;
262
- if (!is_dir_empty (pathname )) {
262
+ if (!is_dir_empty (wpathname )) {
263
263
errno = ENOTEMPTY ;
264
264
break ;
265
265
}
@@ -276,16 +276,26 @@ int mingw_rmdir(const char *pathname)
276
276
while (ret == -1 && errno == EACCES && is_file_in_use_error (GetLastError ()) &&
277
277
ask_yes_no_if_possible ("Deletion of directory '%s' failed. "
278
278
"Should I try again?" , pathname ))
279
- ret = rmdir (pathname );
279
+ ret = _wrmdir (wpathname );
280
+ return ret ;
281
+ }
282
+
283
+ int mingw_mkdir (const char * path , int mode )
284
+ {
285
+ int ret ;
286
+ wchar_t wpath [MAX_PATH ];
287
+ if (xutftowcs_path (wpath , path ) < 0 )
288
+ return -1 ;
289
+ ret = _wmkdir (wpath );
280
290
return ret ;
281
291
}
282
292
283
- #undef open
284
293
int mingw_open (const char * filename , int oflags , ...)
285
294
{
286
295
va_list args ;
287
296
unsigned mode ;
288
297
int fd ;
298
+ wchar_t wfilename [MAX_PATH ];
289
299
290
300
va_start (args , oflags );
291
301
mode = va_arg (args , int );
@@ -294,10 +304,12 @@ int mingw_open (const char *filename, int oflags, ...)
294
304
if (filename && !strcmp (filename , "/dev/null" ))
295
305
filename = "nul" ;
296
306
297
- fd = open (filename , oflags , mode );
307
+ if (xutftowcs_path (wfilename , filename ) < 0 )
308
+ return -1 ;
309
+ fd = _wopen (wfilename , oflags , mode );
298
310
299
311
if (fd < 0 && (oflags & O_CREAT ) && errno == EACCES ) {
300
- DWORD attrs = GetFileAttributes ( filename );
312
+ DWORD attrs = GetFileAttributesW ( wfilename );
301
313
if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY ))
302
314
errno = EISDIR ;
303
315
}
@@ -332,17 +344,28 @@ int mingw_fgetc(FILE *stream)
332
344
#undef fopen
333
345
FILE * mingw_fopen (const char * filename , const char * otype )
334
346
{
347
+ FILE * file ;
348
+ wchar_t wfilename [MAX_PATH ], wotype [4 ];
335
349
if (filename && !strcmp (filename , "/dev/null" ))
336
350
filename = "nul" ;
337
- return fopen (filename , otype );
351
+ if (xutftowcs_path (wfilename , filename ) < 0 ||
352
+ xutftowcs (wotype , otype , ARRAY_SIZE (wotype )) < 0 )
353
+ return NULL ;
354
+ file = _wfopen (wfilename , wotype );
355
+ return file ;
338
356
}
339
357
340
- #undef freopen
341
358
FILE * mingw_freopen (const char * filename , const char * otype , FILE * stream )
342
359
{
360
+ FILE * file ;
361
+ wchar_t wfilename [MAX_PATH ], wotype [4 ];
343
362
if (filename && !strcmp (filename , "/dev/null" ))
344
363
filename = "nul" ;
345
- return freopen (filename , otype , stream );
364
+ if (xutftowcs_path (wfilename , filename ) < 0 ||
365
+ xutftowcs (wotype , otype , ARRAY_SIZE (wotype )) < 0 )
366
+ return NULL ;
367
+ file = _wfreopen (wfilename , wotype , stream );
368
+ return file ;
346
369
}
347
370
348
371
#undef fflush
@@ -367,6 +390,31 @@ int mingw_fflush(FILE *stream)
367
390
return ret ;
368
391
}
369
392
393
+ int mingw_access (const char * filename , int mode )
394
+ {
395
+ wchar_t wfilename [MAX_PATH ];
396
+ if (xutftowcs_path (wfilename , filename ) < 0 )
397
+ return -1 ;
398
+ /* X_OK is not supported by the MSVCRT version */
399
+ return _waccess (wfilename , mode & ~X_OK );
400
+ }
401
+
402
+ int mingw_chdir (const char * dirname )
403
+ {
404
+ wchar_t wdirname [MAX_PATH ];
405
+ if (xutftowcs_path (wdirname , dirname ) < 0 )
406
+ return -1 ;
407
+ return _wchdir (wdirname );
408
+ }
409
+
410
+ int mingw_chmod (const char * filename , int mode )
411
+ {
412
+ wchar_t wfilename [MAX_PATH ];
413
+ if (xutftowcs_path (wfilename , filename ) < 0 )
414
+ return -1 ;
415
+ return _wchmod (wfilename , mode );
416
+ }
417
+
370
418
/*
371
419
* The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
372
420
* Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
@@ -392,10 +440,12 @@ static inline time_t filetime_to_time_t(const FILETIME *ft)
392
440
*/
393
441
static int do_lstat (int follow , const char * file_name , struct stat * buf )
394
442
{
395
- int err ;
396
443
WIN32_FILE_ATTRIBUTE_DATA fdata ;
444
+ wchar_t wfilename [MAX_PATH ];
445
+ if (xutftowcs_path (wfilename , file_name ) < 0 )
446
+ return -1 ;
397
447
398
- if (!( err = get_file_attr ( file_name , & fdata ) )) {
448
+ if (GetFileAttributesExW ( wfilename , GetFileExInfoStandard , & fdata )) {
399
449
buf -> st_ino = 0 ;
400
450
buf -> st_gid = 0 ;
401
451
buf -> st_uid = 0 ;
@@ -408,8 +458,8 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
408
458
buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
409
459
buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
410
460
if (fdata .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) {
411
- WIN32_FIND_DATAA findbuf ;
412
- HANDLE handle = FindFirstFileA ( file_name , & findbuf );
461
+ WIN32_FIND_DATAW findbuf ;
462
+ HANDLE handle = FindFirstFileW ( wfilename , & findbuf );
413
463
if (handle != INVALID_HANDLE_VALUE ) {
414
464
if ((findbuf .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) &&
415
465
(findbuf .dwReserved0 == IO_REPARSE_TAG_SYMLINK )) {
@@ -428,7 +478,23 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
428
478
}
429
479
return 0 ;
430
480
}
431
- errno = err ;
481
+ switch (GetLastError ()) {
482
+ case ERROR_ACCESS_DENIED :
483
+ case ERROR_SHARING_VIOLATION :
484
+ case ERROR_LOCK_VIOLATION :
485
+ case ERROR_SHARING_BUFFER_EXCEEDED :
486
+ errno = EACCES ;
487
+ break ;
488
+ case ERROR_BUFFER_OVERFLOW :
489
+ errno = ENAMETOOLONG ;
490
+ break ;
491
+ case ERROR_NOT_ENOUGH_MEMORY :
492
+ errno = ENOMEM ;
493
+ break ;
494
+ default :
495
+ errno = ENOENT ;
496
+ break ;
497
+ }
432
498
return -1 ;
433
499
}
434
500
@@ -516,16 +582,20 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
516
582
{
517
583
FILETIME mft , aft ;
518
584
int fh , rc ;
585
+ DWORD attrs ;
586
+ wchar_t wfilename [MAX_PATH ];
587
+ if (xutftowcs_path (wfilename , file_name ) < 0 )
588
+ return -1 ;
519
589
520
590
/* must have write permission */
521
- DWORD attrs = GetFileAttributes ( file_name );
591
+ attrs = GetFileAttributesW ( wfilename );
522
592
if (attrs != INVALID_FILE_ATTRIBUTES &&
523
593
(attrs & FILE_ATTRIBUTE_READONLY )) {
524
594
/* ignore errors here; open() will report them */
525
- SetFileAttributes ( file_name , attrs & ~FILE_ATTRIBUTE_READONLY );
595
+ SetFileAttributesW ( wfilename , attrs & ~FILE_ATTRIBUTE_READONLY );
526
596
}
527
597
528
- if ((fh = open ( file_name , O_RDWR | O_BINARY )) < 0 ) {
598
+ if ((fh = _wopen ( wfilename , O_RDWR | O_BINARY )) < 0 ) {
529
599
rc = -1 ;
530
600
goto revert_attrs ;
531
601
}
@@ -548,7 +618,7 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
548
618
if (attrs != INVALID_FILE_ATTRIBUTES &&
549
619
(attrs & FILE_ATTRIBUTE_READONLY )) {
550
620
/* ignore errors again */
551
- SetFileAttributes ( file_name , attrs );
621
+ SetFileAttributesW ( wfilename , attrs );
552
622
}
553
623
return rc ;
554
624
}
@@ -559,6 +629,18 @@ unsigned int sleep (unsigned int seconds)
559
629
return 0 ;
560
630
}
561
631
632
+ char * mingw_mktemp (char * template )
633
+ {
634
+ wchar_t wtemplate [MAX_PATH ];
635
+ if (xutftowcs_path (wtemplate , template ) < 0 )
636
+ return NULL ;
637
+ if (!_wmktemp (wtemplate ))
638
+ return NULL ;
639
+ if (xwcstoutf (template , wtemplate , strlen (template ) + 1 ) < 0 )
640
+ return NULL ;
641
+ return template ;
642
+ }
643
+
562
644
int mkstemp (char * template )
563
645
{
564
646
char * filename = mktemp (template );
@@ -617,17 +699,18 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
617
699
return result ;
618
700
}
619
701
620
- #undef getcwd
621
702
char * mingw_getcwd (char * pointer , int len )
622
703
{
623
704
int i ;
624
- char * ret = getcwd (pointer , len );
625
- if (!ret )
626
- return ret ;
705
+ wchar_t wpointer [MAX_PATH ];
706
+ if (!_wgetcwd (wpointer , ARRAY_SIZE (wpointer )))
707
+ return NULL ;
708
+ if (xwcstoutf (pointer , wpointer , len ) < 0 )
709
+ return NULL ;
627
710
for (i = 0 ; pointer [i ]; i ++ )
628
711
if (pointer [i ] == '\\' )
629
712
pointer [i ] = '/' ;
630
- return ret ;
713
+ return pointer ;
631
714
}
632
715
633
716
#undef getenv
@@ -1468,33 +1551,36 @@ int mingw_rename(const char *pold, const char *pnew)
1468
1551
{
1469
1552
DWORD attrs , gle ;
1470
1553
int tries = 0 ;
1554
+ wchar_t wpold [MAX_PATH ], wpnew [MAX_PATH ];
1555
+ if (xutftowcs_path (wpold , pold ) < 0 || xutftowcs_path (wpnew , pnew ) < 0 )
1556
+ return -1 ;
1471
1557
1472
1558
/*
1473
1559
* Try native rename() first to get errno right.
1474
1560
* It is based on MoveFile(), which cannot overwrite existing files.
1475
1561
*/
1476
- if (!rename ( pold , pnew ))
1562
+ if (!_wrename ( wpold , wpnew ))
1477
1563
return 0 ;
1478
1564
if (errno != EEXIST )
1479
1565
return -1 ;
1480
1566
repeat :
1481
- if (MoveFileEx ( pold , pnew , MOVEFILE_REPLACE_EXISTING ))
1567
+ if (MoveFileExW ( wpold , wpnew , MOVEFILE_REPLACE_EXISTING ))
1482
1568
return 0 ;
1483
1569
/* TODO: translate more errors */
1484
1570
gle = GetLastError ();
1485
1571
if (gle == ERROR_ACCESS_DENIED &&
1486
- (attrs = GetFileAttributes ( pnew )) != INVALID_FILE_ATTRIBUTES ) {
1572
+ (attrs = GetFileAttributesW ( wpnew )) != INVALID_FILE_ATTRIBUTES ) {
1487
1573
if (attrs & FILE_ATTRIBUTE_DIRECTORY ) {
1488
1574
errno = EISDIR ;
1489
1575
return -1 ;
1490
1576
}
1491
1577
if ((attrs & FILE_ATTRIBUTE_READONLY ) &&
1492
- SetFileAttributes ( pnew , attrs & ~FILE_ATTRIBUTE_READONLY )) {
1493
- if (MoveFileEx ( pold , pnew , MOVEFILE_REPLACE_EXISTING ))
1578
+ SetFileAttributesW ( wpnew , attrs & ~FILE_ATTRIBUTE_READONLY )) {
1579
+ if (MoveFileExW ( wpold , wpnew , MOVEFILE_REPLACE_EXISTING ))
1494
1580
return 0 ;
1495
1581
gle = GetLastError ();
1496
1582
/* revert file attributes on failure */
1497
- SetFileAttributes ( pnew , attrs );
1583
+ SetFileAttributesW ( wpnew , attrs );
1498
1584
}
1499
1585
}
1500
1586
if (tries < ARRAY_SIZE (delay ) && gle == ERROR_ACCESS_DENIED ) {
@@ -1740,19 +1826,24 @@ void mingw_open_html(const char *unixpath)
1740
1826
1741
1827
int link (const char * oldpath , const char * newpath )
1742
1828
{
1743
- typedef BOOL (WINAPI * T )(const char * , const char * , LPSECURITY_ATTRIBUTES );
1829
+ typedef BOOL (WINAPI * T )(LPCWSTR , LPCWSTR , LPSECURITY_ATTRIBUTES );
1744
1830
static T create_hard_link = NULL ;
1831
+ wchar_t woldpath [MAX_PATH ], wnewpath [MAX_PATH ];
1832
+ if (xutftowcs_path (woldpath , oldpath ) < 0 ||
1833
+ xutftowcs_path (wnewpath , newpath ) < 0 )
1834
+ return -1 ;
1835
+
1745
1836
if (!create_hard_link ) {
1746
1837
create_hard_link = (T ) GetProcAddress (
1747
- GetModuleHandle ("kernel32.dll" ), "CreateHardLinkA " );
1838
+ GetModuleHandle ("kernel32.dll" ), "CreateHardLinkW " );
1748
1839
if (!create_hard_link )
1749
1840
create_hard_link = (T )- 1 ;
1750
1841
}
1751
1842
if (create_hard_link == (T )- 1 ) {
1752
1843
errno = ENOSYS ;
1753
1844
return -1 ;
1754
1845
}
1755
- if (!create_hard_link (newpath , oldpath , NULL )) {
1846
+ if (!create_hard_link (wnewpath , woldpath , NULL )) {
1756
1847
errno = err_win_to_posix (GetLastError ());
1757
1848
return -1 ;
1758
1849
}
0 commit comments