1
#include "../git-compat-util.h"
2
#include "win32.h"
3
#include <conio.h>
4
+#include <wchar.h>
5
#include "../strbuf.h"
6
#include "../run-command.h"
7
199
}
200
}
201
201
-#undef unlink
202
int mingw_unlink(const char *pathname)
203
{
204
int ret, tries = 0;
205
+ wchar_t wpathname[MAX_PATH];
206
+ if (xutftowcs_path(wpathname, pathname) < 0)
207
+ return -1;
208
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)) {
212
if (!is_file_in_use_error(GetLastError()))
213
break;
214
/*
224
while (ret == -1 && is_file_in_use_error(GetLastError()) &&
225
ask_yes_no_if_possible("Unlink of file '%s' failed. "
226
"Should I try again?", pathname))
224
- ret = unlink(pathname);
227
+ ret = _wunlink(wpathname);
228
return ret;
229
}
230
228
-static int is_dir_empty(const char *path)
231
+static int is_dir_empty(const wchar_t *wpath)
232
{
230
- struct strbuf buf = STRBUF_INIT;
231
- WIN32_FIND_DATAA findbuf;
233
+ WIN32_FIND_DATAW findbuf;
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)
240
return GetLastError() == ERROR_NO_MORE_FILES;
239
- }
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;
248
}
249
FindClose(handle);
248
- strbuf_release(&buf);
250
return 0;
251
}
252
252
-#undef rmdir
253
int mingw_rmdir(const char *pathname)
254
{
255
int ret, tries = 0;
256
+ wchar_t wpathname[MAX_PATH];
257
+ if (xutftowcs_path(wpathname, pathname) < 0)
258
+ return -1;
259
257
- while ((ret = rmdir(pathname)) == -1 && tries < ARRAY_SIZE(delay)) {
260
+ while ((ret = _wrmdir(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
261
if (!is_file_in_use_error(GetLastError()))
262
errno = err_win_to_posix(GetLastError());
263
if (errno != EACCES)
264
break;
262
- if (!is_dir_empty(pathname)) {
265
+ if (!is_dir_empty(wpathname)) {
266
errno = ENOTEMPTY;
267
break;
268
}
279
while (ret == -1 && errno == EACCES && is_file_in_use_error(GetLastError()) &&
280
ask_yes_no_if_possible("Deletion of directory '%s' failed. "
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);
293
return ret;
294
}
295
283
-#undef open
296
int mingw_open (const char *filename, int oflags, ...)
297
{
298
va_list args;
299
unsigned mode;
300
int fd;
301
+ wchar_t wfilename[MAX_PATH];
302
303
va_start(args, oflags);
304
mode = va_arg(args, int);
307
if (filename && !strcmp(filename, "/dev/null"))
308
filename = "nul";
309
297
- fd = open(filename, oflags, mode);
310
+ if (xutftowcs_path(wfilename, filename) < 0)
311
+ return -1;
312
+ fd = _wopen(wfilename, oflags, mode);
313
314
if (fd < 0 && (oflags & O_CREAT) && errno == EACCES) {
300
- DWORD attrs = GetFileAttributes(filename);
315
+ DWORD attrs = GetFileAttributesW(wfilename);
316
if (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY))
317
errno = EISDIR;
318
}
347
#undef fopen
348
FILE *mingw_fopen (const char *filename, const char *otype)
349
{
350
+ FILE *file;
351
+ wchar_t wfilename[MAX_PATH], wotype[4];
352
if (filename && !strcmp(filename, "/dev/null"))
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;
359
}
360
340
-#undef freopen
361
FILE *mingw_freopen (const char *filename, const char *otype, FILE *stream)
362
{
363
+ FILE *file;
364
+ wchar_t wfilename[MAX_PATH], wotype[4];
365
if (filename && !strcmp(filename, "/dev/null"))
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;
372
}
373
374
#undef fflush
393
return ret;
394
}
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
+
421
/*
422
* The unit of FILETIME is 100-nanoseconds since January 1, 1601, UTC.
423
* Returns the 100-nanoseconds ("hekto nanoseconds") since the epoch.
443
*/
444
static int do_lstat(int follow, const char *file_name, struct stat *buf)
445
{
395
- int err;
446
WIN32_FILE_ATTRIBUTE_DATA fdata;
447
+ wchar_t wfilename[MAX_PATH];
448
+ if (xutftowcs_path(wfilename, file_name) < 0)
449
+ return -1;
450
398
- if (!(err = get_file_attr(file_name, &fdata))) {
451
+ if (GetFileAttributesExW(wfilename, GetFileExInfoStandard, &fdata)) {
452
buf->st_ino = 0;
453
buf->st_gid = 0;
454
buf->st_uid = 0;
461
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
462
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
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);
466
if (handle != INVALID_HANDLE_VALUE) {
467
if ((findbuf.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) &&
468
(findbuf.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
481
}
482
return 0;
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
+ }
501
return -1;
502
}
503
585
{
586
FILETIME mft, aft;
587
int fh, rc;
588
+ DWORD attrs;
589
+ wchar_t wfilename[MAX_PATH];
590
+ if (xutftowcs_path(wfilename, file_name) < 0)
591
+ return -1;
592
593
/* must have write permission */
521
- DWORD attrs = GetFileAttributes(file_name);
594
+ attrs = GetFileAttributesW(wfilename);
595
if (attrs != INVALID_FILE_ATTRIBUTES &&
596
(attrs & FILE_ATTRIBUTE_READONLY)) {
597
/* ignore errors here; open() will report them */
525
- SetFileAttributes(file_name, attrs & ~FILE_ATTRIBUTE_READONLY);
598
+ SetFileAttributesW(wfilename, attrs & ~FILE_ATTRIBUTE_READONLY);
599
}
600
528
- if ((fh = open(file_name, O_RDWR | O_BINARY)) < 0) {
601
+ if ((fh = _wopen(wfilename, O_RDWR | O_BINARY)) < 0) {
602
rc = -1;
603
goto revert_attrs;
604
}
621
if (attrs != INVALID_FILE_ATTRIBUTES &&
622
(attrs & FILE_ATTRIBUTE_READONLY)) {
623
/* ignore errors again */
551
- SetFileAttributes(file_name, attrs);
624
+ SetFileAttributesW(wfilename, attrs);
625
}
626
return rc;
627
}
632
return 0;
633
}
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
+
647
int mkstemp(char *template)
648
{
649
char *filename = mktemp(template);
702
return result;
703
}
704
620
-#undef getcwd
705
char *mingw_getcwd(char *pointer, int len)
706
{
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;
713
for (i = 0; pointer[i]; i++)
714
if (pointer[i] == '\\')
715
pointer[i] = '/';
630
- return ret;
716
+ return pointer;
717
}
718
719
/*
1571
{
1572
DWORD attrs, gle;
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;
1577
1578
/*
1579
* Try native rename() first to get errno right.
1580
* It is based on MoveFile(), which cannot overwrite existing files.
1581
*/
1493
- if (!rename(pold, pnew))
1582
+ if (!_wrename(wpold, wpnew))
1583
return 0;
1584
if (errno != EEXIST)
1585
return -1;
1586
repeat:
1498
- if (MoveFileEx(pold, pnew, MOVEFILE_REPLACE_EXISTING))
1587
+ if (MoveFileExW(wpold, wpnew, MOVEFILE_REPLACE_EXISTING))
1588
return 0;
1589
/* TODO: translate more errors */
1590
gle = GetLastError();
1591
if (gle == ERROR_ACCESS_DENIED &&
1503
- (attrs = GetFileAttributes(pnew)) != INVALID_FILE_ATTRIBUTES) {
1592
+ (attrs = GetFileAttributesW(wpnew)) != INVALID_FILE_ATTRIBUTES) {
1593
if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
1594
errno = EISDIR;
1595
return -1;
1596
}
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))
1600
return 0;
1601
gle = GetLastError();
1602
/* revert file attributes on failure */
1514
- SetFileAttributes(pnew, attrs);
1603
+ SetFileAttributesW(wpnew, attrs);
1604
}
1605
}
1606
if (tries < ARRAY_SIZE(delay) && gle == ERROR_ACCESS_DENIED) {
1846
1847
int link(const char *oldpath, const char *newpath)
1848
{
1760
- typedef BOOL (WINAPI *T)(const char*, const char*, LPSECURITY_ATTRIBUTES);
1849
+ typedef BOOL (WINAPI *T)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
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
+
1856
if (!create_hard_link) {
1857
create_hard_link = (T) GetProcAddress(
1764
- GetModuleHandle("kernel32.dll"), "CreateHardLinkA");
1858
+ GetModuleHandle("kernel32.dll"), "CreateHardLinkW");
1859
if (!create_hard_link)
1860
create_hard_link = (T)-1;
1861
}
1863
errno = ENOSYS;
1864
return -1;
1865
}
1772
- if (!create_hard_link(newpath, oldpath, NULL)) {
1866
+ if (!create_hard_link(wnewpath, woldpath, NULL)) {
1867
errno = err_win_to_posix(GetLastError());
1868
return -1;
1869
}