199
efile_mkdir(errInfo, name)
200
Efile_error* errInfo; /* Where to return error codes. */
201
char* name; /* Name of directory to create. */
199
efile_mkdir(Efile_error* errInfo, /* Where to return error codes. */
200
char* name) /* Name of directory to create. */
203
return check_error(mkdir(name), errInfo);
202
return check_error(_wmkdir((WCHAR *) name), errInfo);
207
efile_rmdir(errInfo, name)
208
Efile_error* errInfo; /* Where to return error codes. */
209
char* name; /* Name of directory to delete. */
206
efile_rmdir(Efile_error* errInfo, /* Where to return error codes. */
207
char* name) /* Name of directory to delete. */
211
209
OSVERSIONINFO os;
211
WCHAR *wname = (WCHAR *) name;
214
if (RemoveDirectory(name) != FALSE) {
213
if (RemoveDirectoryW(wname) != FALSE) {
217
216
errno = errno_map(GetLastError());
218
217
if (errno == EACCES) {
219
attr = GetFileAttributes(name);
218
attr = GetFileAttributesW(wname);
220
219
if (attr != (DWORD) -1) {
221
220
if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
238
237
GetVersionEx(&os);
239
238
if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
241
WIN32_FIND_DATA data;
242
char buffer[2*MAX_PATH];
240
WIN32_FIND_DATAW data;
241
WCHAR buffer[2*MAX_PATH];
246
strcpy(buffer, name);
247
if (buffer[0] && buffer[len-1] != '\\' && buffer[len-1] != '/') {
248
strcat(buffer, "\\");
245
wcscpy(buffer, wname);
246
if (buffer[0] && buffer[len-1] != L'\\' && buffer[len-1] != L'/') {
247
wcscat(buffer, L"\\");
250
strcat(buffer, "*.*");
251
handle = FindFirstFile(buffer, &data);
249
wcscat(buffer, L"*.*");
250
handle = FindFirstFileW(buffer, &data);
252
251
if (handle != INVALID_HANDLE_VALUE) {
254
if ((strcmp(data.cFileName, ".") != 0)
255
&& (strcmp(data.cFileName, "..") != 0)) {
253
if ((wcscmp(data.cFileName, L".") != 0)
254
&& (wcscmp(data.cFileName, L"..") != 0)) {
257
256
* Found something in this directory.
287
efile_delete_file(errInfo, name)
288
Efile_error* errInfo; /* Where to return error codes. */
289
char* name; /* Name of file to delete. */
286
efile_delete_file(Efile_error* errInfo, /* Where to return error codes. */
287
char* name) /* Name of file to delete. */
290
WCHAR *wname = (WCHAR *) name;
293
if (DeleteFile(name) != FALSE) {
292
if (DeleteFileW(wname) != FALSE) {
297
296
errno = errno_map(GetLastError());
298
297
if (errno == EACCES) {
299
attr = GetFileAttributes(name);
298
attr = GetFileAttributesW(wname);
300
299
if (attr != (DWORD) -1) {
301
300
if (attr & FILE_ATTRIBUTE_DIRECTORY) {
365
efile_rename(errInfo, src, dst)
366
Efile_error* errInfo; /* Where to return error codes. */
367
char* src; /* Original name. */
368
char* dst; /* New name. */
364
efile_rename(Efile_error* errInfo, /* Where to return error codes. */
365
char* src, /* Original name. */
366
char* dst) /* New name. */
370
368
DWORD srcAttr, dstAttr;
369
WCHAR *wsrc = (WCHAR *) src;
370
WCHAR *wdst = (WCHAR *) dst;
372
if (MoveFile(src, dst) != FALSE) {
372
if (MoveFileW(wsrc, wdst) != FALSE) {
376
376
errno = errno_map(GetLastError());
377
srcAttr = GetFileAttributes(src);
378
dstAttr = GetFileAttributes(dst);
377
srcAttr = GetFileAttributesW(wsrc);
378
dstAttr = GetFileAttributesW(wdst);
379
379
if (srcAttr == (DWORD) -1) {
390
390
if (errno == EACCES) {
392
392
if (srcAttr & FILE_ATTRIBUTE_DIRECTORY) {
393
char srcPath[MAX_PATH], dstPath[MAX_PATH];
394
char *srcRest, *dstRest;
393
WCHAR srcPath[MAX_PATH], dstPath[MAX_PATH];
394
WCHAR *srcRest, *dstRest;
397
size = GetFullPathName(src, sizeof(srcPath), srcPath, &srcRest);
398
if ((size == 0) || (size > sizeof(srcPath))) {
397
size = GetFullPathNameW(wsrc, MAX_PATH, srcPath, &srcRest);
398
if ((size == 0) || (size > MAX_PATH)) {
399
399
return check_error(-1, errInfo);
401
size = GetFullPathName(dst, sizeof(dstPath), dstPath, &dstRest);
402
if ((size == 0) || (size > sizeof(dstPath))) {
401
size = GetFullPathNameW(wdst, MAX_PATH, dstPath, &dstRest);
402
if ((size == 0) || (size > MAX_PATH)) {
403
403
return check_error(-1, errInfo);
405
405
if (srcRest == NULL) {
406
srcRest = srcPath + strlen(srcPath);
406
srcRest = srcPath + wcslen(srcPath);
408
if (strnicmp(srcPath, dstPath, srcRest - srcPath) == 0) {
408
if (_wcsnicmp(srcPath, dstPath, srcRest - srcPath) == 0) {
410
410
* Trying to move a directory into itself.
506
506
* put temp file back to old name.
509
char tempName[MAX_PATH];
509
WCHAR tempName[MAX_PATH];
510
510
int result, size;
513
size = GetFullPathName(dst, sizeof(tempName), tempName, &rest);
514
if ((size == 0) || (size > sizeof(tempName)) || (rest == NULL)) {
513
size = GetFullPathNameW(wdst, MAX_PATH, tempName, &rest);
514
if ((size == 0) || (size > MAX_PATH) || (rest == NULL)) {
515
515
return check_error(-1, errInfo);
519
if (GetTempFileName(tempName, "erlr", 0, tempName) != 0) {
519
if (GetTempFileNameW(tempName, L"erlr", 0, tempName) != 0) {
521
521
* Strictly speaking, need the following DeleteFile and
522
522
* MoveFile to be joined as an atomic operation so no
573
efile_getdcwd(errInfo, drive, buffer, size)
574
Efile_error* errInfo; /* Where to return error codes. */
575
int drive; /* 0 - current, 1 - A, 2 - B etc. */
576
char* buffer; /* Where to return the current directory. */
577
size_t size; /* Size of buffer. */
572
efile_getdcwd(Efile_error* errInfo, /* Where to return error codes. */
573
int drive, /* 0 - current, 1 - A, 2 - B etc. */
574
char* buffer, /* Where to return the current directory. */
575
size_t size) /* Size of buffer. */
579
if (_getdcwd(drive, buffer, size) == NULL)
577
WCHAR *wbuffer = (WCHAR *) buffer;
578
size_t wbuffer_size = size / 2;
579
if (_wgetdcwd(drive, wbuffer, wbuffer_size) == NULL)
580
580
return check_error(-1, errInfo);
581
for ( ; *buffer; buffer++)
581
for ( ; *wbuffer; wbuffer++)
582
if (*wbuffer == L'\\')
588
efile_readdir(errInfo, name, dir_handle, buffer, size)
589
Efile_error* errInfo; /* Where to return error codes. */
590
char* name; /* Name of directory to open. */
591
EFILE_DIR_HANDLE* dir_handle; /* Directory handle of open directory. */
592
char* buffer; /* Pointer to buffer for one filename. */
593
size_t size; /* Size of buffer. */
588
efile_readdir(Efile_error* errInfo, /* Where to return error codes. */
589
char* name, /* Name of directory to list */
590
EFILE_DIR_HANDLE* dir_handle, /* Handle of opened directory or NULL */
591
char* buffer, /* Buffer to put one filename in */
592
size_t *size) /* in-out size of buffer/size of filename excluding zero
593
termination in bytes*/
595
595
HANDLE dir; /* Handle to directory. */
596
char wildcard[MAX_PATH]; /* Wildcard to search for. */
597
WIN32_FIND_DATA findData; /* Data found by FindFirstFile() or FindNext(). */
596
WCHAR wildcard[MAX_PATH]; /* Wildcard to search for. */
597
WIN32_FIND_DATAW findData; /* Data found by FindFirstFile() or FindNext(). */
598
/* Alignment is not honored, this works on x86 because of alignment fixup by processor.
599
Not perfect, but faster than alinging by hand (really) */
600
WCHAR *wname = (WCHAR *) name;
601
WCHAR *wbuffer = (WCHAR *) buffer;
600
604
* First time we must setup everything.
603
607
if (*dir_handle == NULL) {
604
int length = strlen(name);
608
int length = wcslen(wname);
607
611
if (length+3 >= MAX_PATH) {
608
612
errno = ENAMETOOLONG;
609
613
return check_error(-1, errInfo);
612
strcpy(wildcard, name);
616
wcscpy(wildcard, wname);
613
617
s = wildcard+length-1;
614
if (*s != '/' && *s != '\\')
618
DEBUGF(("Reading %s\n", wildcard));
619
dir = FindFirstFile(wildcard, &findData);
618
if (*s != L'/' && *s != L'\\')
622
DEBUGF(("Reading %ws\n", wildcard));
623
dir = FindFirstFileW(wildcard, &findData);
620
624
if (dir == INVALID_HANDLE_VALUE)
621
625
return set_error(errInfo);
622
626
*dir_handle = (EFILE_DIR_HANDLE) dir;
624
628
if (!IS_DOT_OR_DOTDOT(findData.cFileName)) {
625
strcpy(buffer, findData.cFileName);
629
wcscpy(wbuffer, findData.cFileName);
630
*size = wcslen(wbuffer)*2;
658
efile_openfile(errInfo, name, flags, pfd, pSize)
659
Efile_error* errInfo; /* Where to return error codes. */
660
char* name; /* Name of directory to open. */
661
int flags; /* Flags to use for opening. */
662
int* pfd; /* Where to store the file descriptor. */
663
Sint64* pSize; /* Where to store the size of the file. */
664
efile_openfile(Efile_error* errInfo, /* Where to return error codes. */
665
char* name, /* Name of directory to open. */
666
int flags, /* Flags to use for opening. */
667
int* pfd, /* Where to store the file descriptor. */
668
Sint64* pSize) /* Where to store the size of the file. */
665
670
BY_HANDLE_FILE_INFORMATION fileInfo; /* File information from a handle. */
666
671
HANDLE fd; /* Handle to open file. */
667
672
DWORD access; /* Access mode: GENERIC_READ, GENERIC_WRITE. */
674
WCHAR *wname = (WCHAR *) name;
670
676
switch (flags & (EFILE_MODE_READ|EFILE_MODE_WRITE)) {
671
677
case EFILE_MODE_READ:
779
787
char* orig_name, int info_for_link)
781
789
HANDLE findhandle; /* Handle returned by FindFirstFile(). */
782
WIN32_FIND_DATA findbuf; /* Data return by FindFirstFile(). */
783
char name[_MAX_PATH];
790
WIN32_FIND_DATAW findbuf; /* Data return by FindFirstFile(). */
791
WCHAR name[_MAX_PATH];
786
char pathbuf[_MAX_PATH];
794
WCHAR pathbuf[_MAX_PATH];
787
795
int drive; /* Drive for filename (1 = A:, 2 = B: etc). */
796
WCHAR *worig_name = (WCHAR *) orig_name;
789
798
/* Don't allow wildcards to be interpreted by system */
791
if (strpbrk(orig_name, "?*")) {
800
if (wcspbrk(worig_name, L"?*")) {
793
802
errInfo->posix_errno = ENOENT;
794
803
errInfo->os_errno = ERROR_FILE_NOT_FOUND;
800
809
* slash, because it causes FindFirstFile() to fail on Win95.
803
if ((name_len = strlen(orig_name)) >= _MAX_PATH) {
812
if ((name_len = wcslen(worig_name)) >= _MAX_PATH) {
806
strcpy(name, orig_name);
815
wcscpy(name, worig_name);
807
816
if (name_len > 2 && ISSLASH(name[name_len-1]) &&
808
name[name_len-2] != ':') {
809
name[name_len-1] = '\0';
817
name[name_len-2] != L':') {
818
name[name_len-1] = L'\0';
813
822
/* Try to get disk from name. If none, get current disk. */
815
if (name[1] != ':') {
824
if (name[1] != L':') {
817
if (GetCurrentDirectory(sizeof(pathbuf), pathbuf) &&
819
drive = tolower(pathbuf[0]) - 'a' + 1;
826
if (GetCurrentDirectoryW(_MAX_PATH, pathbuf) &&
827
pathbuf[1] == L':') {
828
drive = towlower(pathbuf[0]) - L'a' + 1;
821
} else if (*name && name[2] == '\0') {
830
} else if (*name && name[2] == L'\0') {
823
832
* X: and nothing more is an error.
826
835
errInfo->os_errno = ERROR_FILE_NOT_FOUND;
829
drive = tolower(*name) - 'a' + 1;
838
drive = towlower(*name) - L'a' + 1;
831
findhandle = FindFirstFile(name, &findbuf);
840
findhandle = FindFirstFileW(name, &findbuf);
832
841
if (findhandle == INVALID_HANDLE_VALUE) {
833
if (!(strpbrk(name, "./\\") &&
834
(path = _fullpath(pathbuf, name, _MAX_PATH)) &&
842
if (!(wcspbrk(name, L"./\\") &&
843
(path = _wfullpath(pathbuf, name, _MAX_PATH)) &&
835
844
/* root dir. ('C:\') or UNC root dir. ('\\server\share\') */
836
((strlen(path) == 3) || IsRootUNCName(path)) &&
837
(GetDriveType(path) > 1) ) ) {
845
((wcslen(path) == 3) || is_root_unc_name(path)) &&
846
(GetDriveTypeW(path) > 1) ) ) {
838
847
errInfo->posix_errno = ENOENT;
839
848
errInfo->os_errno = ERROR_FILE_NOT_FOUND;
861
871
SYSTEMTIME SystemTime;
862
872
FILETIME LocalFTime;
874
/*first check if we are a symlink */
875
if (!info_for_link && (findbuf.dwFileAttributes &
876
FILE_ATTRIBUTE_REPARSE_POINT)){
878
* given that we know this is a symlink,
879
we should be able to find its target */
880
WCHAR target_name[_MAX_PATH];
881
if (efile_readlink(errInfo, (char *) name,
882
(char *) target_name,256) == 1) {
883
FindClose(findhandle);
884
return efile_fileinfo(errInfo, pInfo,
885
(char *) target_name, info_for_link);
889
/* number of links: */
891
HANDLE handle; /* Handle returned by CreateFile() */
892
BY_HANDLE_FILE_INFORMATION fileInfo; /* from CreateFile() */
893
if (handle = CreateFileW(name, GENERIC_READ, 0,NULL,
894
OPEN_EXISTING, 0, NULL)) {
895
GetFileInformationByHandle(handle, &fileInfo);
896
pInfo->links = fileInfo.nNumberOfLinks;
864
903
#define GET_TIME(dst, src) \
865
904
if (!FileTimeToLocalFileTime(&findbuf.src, &LocalFTime) || \
866
905
!FileTimeToSystemTime(&LocalFTime, &SystemTime)) { \
994
1035
if (tempAttr & FILE_ATTRIBUTE_READONLY) {
995
1036
tempAttr &= ~FILE_ATTRIBUTE_READONLY;
996
if (!SetFileAttributes((LPTSTR) name, tempAttr)) {
1037
if (!SetFileAttributesW(wname, tempAttr)) {
997
1038
return set_error(errInfo);
1001
fd = CreateFile(name, GENERIC_READ|GENERIC_WRITE,
1042
fd = CreateFileW(wname, GENERIC_READ|GENERIC_WRITE,
1002
1043
FILE_SHARE_READ | FILE_SHARE_WRITE,
1003
1044
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
1004
1045
if (fd != INVALID_HANDLE_VALUE) {
1069
1110
size_t count; /* Number of bytes to write. */
1071
1112
DWORD written; /* Bytes written in last operation. */
1113
OVERLAPPED overlapped;
1114
OVERLAPPED* pOverlapped = NULL;
1073
1116
if (flags & EFILE_MODE_APPEND) {
1074
(void) SetFilePointer((HANDLE) fd, 0, NULL, FILE_END);
1117
memset(&overlapped, 0, sizeof(overlapped));
1118
overlapped.Offset = 0xffffffff;
1119
overlapped.OffsetHigh = 0xffffffff;
1120
pOverlapped = &overlapped;
1076
1122
while (count > 0) {
1077
if (!WriteFile((HANDLE) fd, buf, count, &written, NULL))
1123
if (!WriteFile((HANDLE) fd, buf, count, &written, pOverlapped))
1078
1124
return set_error(errInfo);
1079
1125
buf += written;
1080
1126
count -= written;
1331
1382
efile_readlink(Efile_error* errInfo, char* name, char* buffer, size_t size)
1385
* load dll and see if we have CreateSymbolicLink at runtime:
1388
HINSTANCE hModule = NULL;
1389
WCHAR *wname = (WCHAR *) name;
1390
WCHAR *wbuffer = (WCHAR *) buffer;
1391
if ((hModule = LoadLibrary("kernel32.dll")) != NULL) {
1392
typedef DWORD (WINAPI * GETFINALPATHNAMEBYHANDLEPTR)(
1398
GETFINALPATHNAMEBYHANDLEPTR pGetFinalPathNameByHandle =
1399
(GETFINALPATHNAMEBYHANDLEPTR)GetProcAddress(hModule, "GetFinalPathNameByHandleW");
1401
if (pGetFinalPathNameByHandle == NULL) {
1402
FreeLibrary(hModule);
1404
/* first check if file is a symlink; {error, einval} otherwise */
1405
DWORD fileAttributes = GetFileAttributesW(wname);
1406
if ((fileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
1407
BOOLEAN success = 0;
1408
HANDLE h = CreateFileW(wname, GENERIC_READ, 0,NULL, OPEN_EXISTING, 0, NULL);
1410
if(h != INVALID_HANDLE_VALUE) {
1411
success = pGetFinalPathNameByHandle(h, wbuffer, size,0);
1412
/* GetFinalPathNameByHandle prepends path with "\\?\": */
1413
len = wcslen(wbuffer);
1414
wmemmove(wbuffer,wbuffer+4,len-3);
1415
if (len - 4 >= 2 && wbuffer[1] == L':' && wbuffer[0] >= L'A' &&
1416
wbuffer[0] <= L'Z') {
1417
wbuffer[0] = wbuffer[0] + L'a' - L'A';
1420
for ( ; *wbuffer; wbuffer++)
1421
if (*wbuffer == L'\\')
1425
FreeLibrary(hModule);
1429
return set_error(errInfo);
1432
FreeLibrary(hModule);
1434
return check_error(-1, errInfo);
1333
1438
errno = ENOTSUP;
1334
1439
return check_error(-1, errInfo);
1360
1468
* slash, because it causes FindFirstFile() to fail on Win95.
1363
if ((name_len = strlen(orig_name)) >= _MAX_PATH) {
1471
if ((name_len = wcslen(worig_name)) >= _MAX_PATH) {
1366
strcpy(name, orig_name);
1474
wcscpy(name, worig_name);
1367
1475
if (name_len > 2 && ISSLASH(name[name_len-1]) &&
1368
name[name_len-2] != ':') {
1369
name[name_len-1] = '\0';
1476
name[name_len-2] != L':') {
1477
name[name_len-1] = L'\0';
1373
1481
/* Try to get disk from name. If none, get current disk. */
1375
if (name[1] != ':') {
1483
if (name[1] != L':') {
1377
if (GetCurrentDirectory(sizeof(pathbuf), pathbuf) &&
1378
pathbuf[1] == ':') {
1379
drive = tolower(pathbuf[0]) - 'a' + 1;
1485
if (GetCurrentDirectoryW(_MAX_PATH, pathbuf) &&
1486
pathbuf[1] == L':') {
1487
drive = towlower(pathbuf[0]) - L'a' + 1;
1381
} else if (*name && name[2] == '\0') {
1489
} else if (*name && name[2] == L'\0') {
1383
1491
* X: and nothing more is an error.
1387
drive = tolower(*name) - 'a' + 1;
1495
drive = towlower(*name) - L'a' + 1;
1389
fh = FindFirstFile(name,&wfd);
1497
fh = FindFirstFileW(name,&wfd);
1390
1498
if (fh == INVALID_HANDLE_VALUE) {
1391
if (!(strpbrk(name, "./\\") &&
1392
(path = _fullpath(pathbuf, name, _MAX_PATH)) &&
1499
if (!(wcspbrk(name, L"./\\") &&
1500
(path = _wfullpath(pathbuf, name, _MAX_PATH)) &&
1393
1501
/* root dir. ('C:\') or UNC root dir. ('\\server\share\') */
1394
((strlen(path) == 3) || IsRootUNCName(path)) &&
1395
(GetDriveType(path) > 1) ) ) {
1502
((wcslen(path) == 3) || is_root_unc_name(path)) &&
1503
(GetDriveTypeW(path) > 1) ) ) {
1396
1504
errno = errno_map(GetLastError());
1397
1505
return check_error(-1, errInfo);
1400
1508
* Root directories (such as C:\ or \\server\share\ are fabricated.
1402
strcpy(buffer,name);
1510
wcscpy(wbuffer,name);
1406
strcpy(buffer,wfd.cAlternateFileName);
1408
strcpy(buffer,wfd.cFileName);
1514
wcscpy(wbuffer,wfd.cAlternateFileName);
1516
wcscpy(wbuffer,wfd.cFileName);
1415
1524
efile_link(Efile_error* errInfo, char* old, char* new)
1418
return check_error(-1, errInfo);
1526
WCHAR *wold = (WCHAR *) old;
1527
WCHAR *wnew = (WCHAR *) new;
1528
if(!CreateHardLinkW(wnew, wold, NULL)) {
1529
return set_error(errInfo);
1422
1535
efile_symlink(Efile_error* errInfo, char* old, char* new)
1538
* Load dll and see if we have CreateSymbolicLink at runtime:
1541
HINSTANCE hModule = NULL;
1542
WCHAR *wold = (WCHAR *) old;
1543
WCHAR *wnew = (WCHAR *) new;
1544
if ((hModule = LoadLibrary("kernel32.dll")) != NULL) {
1545
typedef BOOLEAN (WINAPI * CREATESYMBOLICLINKFUNCPTR) (
1546
LPCWSTR lpSymlinkFileName,
1547
LPCWSTR lpTargetFileName,
1550
CREATESYMBOLICLINKFUNCPTR pCreateSymbolicLink =
1551
(CREATESYMBOLICLINKFUNCPTR) GetProcAddress(hModule,
1552
"CreateSymbolicLinkW");
1553
/* A for MBCS, W for UNICODE... char* above implies 'W'! */
1554
if (pCreateSymbolicLink != NULL) {
1555
DWORD attr = GetFileAttributesW(wold);
1556
int flag = (attr != INVALID_FILE_ATTRIBUTES &&
1557
attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
1558
/* SYMBOLIC_LINK_FLAG_DIRECTORY = 1 */
1559
BOOLEAN success = pCreateSymbolicLink(wnew, wold, flag);
1560
FreeLibrary(hModule);
1565
return set_error(errInfo);
1568
FreeLibrary(hModule);
1424
1570
errno = ENOTSUP;
1425
1571
return check_error(-1, errInfo);
1575
efile_fadvise(Efile_error* errInfo, int fd, Sint64 offset,
1576
Sint64 length, int advise)
1578
/* posix_fadvise is not available on Windows, do nothing */
1579
errno = ERROR_SUCCESS;
1580
return check_error(0, errInfo);