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,45 @@ 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 );
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 ;
246
248
}
247
249
FindClose (handle );
248
- strbuf_release (& buf );
249
250
return 0 ;
250
251
}
251
252
252
- #undef rmdir
253
253
int mingw_rmdir (const char * pathname )
254
254
{
255
255
int ret , tries = 0 ;
256
+ wchar_t wpathname [MAX_PATH ];
257
+ if (xutftowcs_path (wpathname , pathname ) < 0 )
258
+ return -1 ;
256
259
257
- while ((ret = rmdir ( pathname )) == -1 && tries < ARRAY_SIZE (delay )) {
260
+ while ((ret = _wrmdir ( wpathname )) == -1 && tries < ARRAY_SIZE (delay )) {
258
261
if (!is_file_in_use_error (GetLastError ()))
259
262
errno = err_win_to_posix (GetLastError ());
260
263
if (errno != EACCES )
261
264
break ;
262
- if (!is_dir_empty (pathname )) {
265
+ if (!is_dir_empty (wpathname )) {
263
266
errno = ENOTEMPTY ;
264
267
break ;
265
268
}
@@ -276,16 +279,26 @@ int mingw_rmdir(const char *pathname)
276
279
while (ret == -1 && errno == EACCES && is_file_in_use_error (GetLastError ()) &&
277
280
ask_yes_no_if_possible ("Deletion of directory '%s' failed. "
278
281
"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 );
280
293
return ret ;
281
294
}
282
295
283
- #undef open
284
296
int mingw_open (const char * filename , int oflags , ...)
285
297
{
286
298
va_list args ;
287
299
unsigned mode ;
288
300
int fd ;
301
+ wchar_t wfilename [MAX_PATH ];
289
302
290
303
va_start (args , oflags );
291
304
mode = va_arg (args , int );
@@ -294,10 +307,12 @@ int mingw_open (const char *filename, int oflags, ...)
294
307
if (filename && !strcmp (filename , "/dev/null" ))
295
308
filename = "nul" ;
296
309
297
- fd = open (filename , oflags , mode );
310
+ if (xutftowcs_path (wfilename , filename ) < 0 )
311
+ return -1 ;
312
+ fd = _wopen (wfilename , oflags , mode );
298
313
299
314
if (fd < 0 && (oflags & O_CREAT ) && errno == EACCES ) {
300
- DWORD attrs = GetFileAttributes ( filename );
315
+ DWORD attrs = GetFileAttributesW ( wfilename );
301
316
if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY ))
302
317
errno = EISDIR ;
303
318
}
@@ -332,17 +347,28 @@ int mingw_fgetc(FILE *stream)
332
347
#undef fopen
333
348
FILE * mingw_fopen (const char * filename , const char * otype )
334
349
{
350
+ FILE * file ;
351
+ wchar_t wfilename [MAX_PATH ], wotype [4 ];
335
352
if (filename && !strcmp (filename , "/dev/null" ))
336
353
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 ;
338
359
}
339
360
340
- #undef freopen
341
361
FILE * mingw_freopen (const char * filename , const char * otype , FILE * stream )
342
362
{
363
+ FILE * file ;
364
+ wchar_t wfilename [MAX_PATH ], wotype [4 ];
343
365
if (filename && !strcmp (filename , "/dev/null" ))
344
366
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 ;
346
372
}
347
373
348
374
#undef fflush
@@ -367,6 +393,31 @@ int mingw_fflush(FILE *stream)
367
393
return ret ;
368
394
}
369
395
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
+
370
421
/*
371
422
* The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
372
423
* Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
@@ -392,10 +443,12 @@ static inline time_t filetime_to_time_t(const FILETIME *ft)
392
443
*/
393
444
static int do_lstat (int follow , const char * file_name , struct stat * buf )
394
445
{
395
- int err ;
396
446
WIN32_FILE_ATTRIBUTE_DATA fdata ;
447
+ wchar_t wfilename [MAX_PATH ];
448
+ if (xutftowcs_path (wfilename , file_name ) < 0 )
449
+ return -1 ;
397
450
398
- if (!( err = get_file_attr ( file_name , & fdata ) )) {
451
+ if (GetFileAttributesExW ( wfilename , GetFileExInfoStandard , & fdata )) {
399
452
buf -> st_ino = 0 ;
400
453
buf -> st_gid = 0 ;
401
454
buf -> st_uid = 0 ;
@@ -408,8 +461,8 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
408
461
buf -> st_mtime = filetime_to_time_t (& (fdata .ftLastWriteTime ));
409
462
buf -> st_ctime = filetime_to_time_t (& (fdata .ftCreationTime ));
410
463
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 );
413
466
if (handle != INVALID_HANDLE_VALUE ) {
414
467
if ((findbuf .dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ) &&
415
468
(findbuf .dwReserved0 == IO_REPARSE_TAG_SYMLINK )) {
@@ -428,7 +481,23 @@ static int do_lstat(int follow, const char *file_name, struct stat *buf)
428
481
}
429
482
return 0 ;
430
483
}
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
+ }
432
501
return -1 ;
433
502
}
434
503
@@ -516,16 +585,20 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
516
585
{
517
586
FILETIME mft , aft ;
518
587
int fh , rc ;
588
+ DWORD attrs ;
589
+ wchar_t wfilename [MAX_PATH ];
590
+ if (xutftowcs_path (wfilename , file_name ) < 0 )
591
+ return -1 ;
519
592
520
593
/* must have write permission */
521
- DWORD attrs = GetFileAttributes ( file_name );
594
+ attrs = GetFileAttributesW ( wfilename );
522
595
if (attrs != INVALID_FILE_ATTRIBUTES &&
523
596
(attrs & FILE_ATTRIBUTE_READONLY )) {
524
597
/* ignore errors here; open() will report them */
525
- SetFileAttributes ( file_name , attrs & ~FILE_ATTRIBUTE_READONLY );
598
+ SetFileAttributesW ( wfilename , attrs & ~FILE_ATTRIBUTE_READONLY );
526
599
}
527
600
528
- if ((fh = open ( file_name , O_RDWR | O_BINARY )) < 0 ) {
601
+ if ((fh = _wopen ( wfilename , O_RDWR | O_BINARY )) < 0 ) {
529
602
rc = -1 ;
530
603
goto revert_attrs ;
531
604
}
@@ -548,7 +621,7 @@ int mingw_utime (const char *file_name, const struct utimbuf *times)
548
621
if (attrs != INVALID_FILE_ATTRIBUTES &&
549
622
(attrs & FILE_ATTRIBUTE_READONLY )) {
550
623
/* ignore errors again */
551
- SetFileAttributes ( file_name , attrs );
624
+ SetFileAttributesW ( wfilename , attrs );
552
625
}
553
626
return rc ;
554
627
}
@@ -559,6 +632,18 @@ unsigned int sleep (unsigned int seconds)
559
632
return 0 ;
560
633
}
561
634
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
+
562
647
int mkstemp (char * template )
563
648
{
564
649
char * filename = mktemp (template );
@@ -617,17 +702,18 @@ struct tm *localtime_r(const time_t *timep, struct tm *result)
617
702
return result ;
618
703
}
619
704
620
- #undef getcwd
621
705
char * mingw_getcwd (char * pointer , int len )
622
706
{
623
707
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 ;
627
713
for (i = 0 ; pointer [i ]; i ++ )
628
714
if (pointer [i ] == '\\' )
629
715
pointer [i ] = '/' ;
630
- return ret ;
716
+ return pointer ;
631
717
}
632
718
633
719
/*
@@ -1485,33 +1571,36 @@ int mingw_rename(const char *pold, const char *pnew)
1485
1571
{
1486
1572
DWORD attrs , gle ;
1487
1573
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 ;
1488
1577
1489
1578
/*
1490
1579
* Try native rename() first to get errno right.
1491
1580
* It is based on MoveFile(), which cannot overwrite existing files.
1492
1581
*/
1493
- if (!rename ( pold , pnew ))
1582
+ if (!_wrename ( wpold , wpnew ))
1494
1583
return 0 ;
1495
1584
if (errno != EEXIST )
1496
1585
return -1 ;
1497
1586
repeat :
1498
- if (MoveFileEx ( pold , pnew , MOVEFILE_REPLACE_EXISTING ))
1587
+ if (MoveFileExW ( wpold , wpnew , MOVEFILE_REPLACE_EXISTING ))
1499
1588
return 0 ;
1500
1589
/* TODO: translate more errors */
1501
1590
gle = GetLastError ();
1502
1591
if (gle == ERROR_ACCESS_DENIED &&
1503
- (attrs = GetFileAttributes ( pnew )) != INVALID_FILE_ATTRIBUTES ) {
1592
+ (attrs = GetFileAttributesW ( wpnew )) != INVALID_FILE_ATTRIBUTES ) {
1504
1593
if (attrs & FILE_ATTRIBUTE_DIRECTORY ) {
1505
1594
errno = EISDIR ;
1506
1595
return -1 ;
1507
1596
}
1508
1597
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 ))
1511
1600
return 0 ;
1512
1601
gle = GetLastError ();
1513
1602
/* revert file attributes on failure */
1514
- SetFileAttributes ( pnew , attrs );
1603
+ SetFileAttributesW ( wpnew , attrs );
1515
1604
}
1516
1605
}
1517
1606
if (tries < ARRAY_SIZE (delay ) && gle == ERROR_ACCESS_DENIED ) {
@@ -1757,19 +1846,24 @@ void mingw_open_html(const char *unixpath)
1757
1846
1758
1847
int link (const char * oldpath , const char * newpath )
1759
1848
{
1760
- typedef BOOL (WINAPI * T )(const char * , const char * , LPSECURITY_ATTRIBUTES );
1849
+ typedef BOOL (WINAPI * T )(LPCWSTR , LPCWSTR , LPSECURITY_ATTRIBUTES );
1761
1850
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
+
1762
1856
if (!create_hard_link ) {
1763
1857
create_hard_link = (T ) GetProcAddress (
1764
- GetModuleHandle ("kernel32.dll" ), "CreateHardLinkA " );
1858
+ GetModuleHandle ("kernel32.dll" ), "CreateHardLinkW " );
1765
1859
if (!create_hard_link )
1766
1860
create_hard_link = (T )- 1 ;
1767
1861
}
1768
1862
if (create_hard_link == (T )- 1 ) {
1769
1863
errno = ENOSYS ;
1770
1864
return -1 ;
1771
1865
}
1772
- if (!create_hard_link (newpath , oldpath , NULL )) {
1866
+ if (!create_hard_link (wnewpath , woldpath , NULL )) {
1773
1867
errno = err_win_to_posix (GetLastError ());
1774
1868
return -1 ;
1775
1869
}
0 commit comments