ecere: Initial Emscripten support
[sdk] / ecere / src / sys / File.c
1 #define _Noreturn
2
3 #undef __BLOCKS__
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8 #include <ctype.h>
9
10 #if defined(__GNUC__) || defined(__WATCOMC__) || defined(__WIN32__)
11 #include <time.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #endif
16
17 #if defined(__unix__) || defined(__APPLE__)
18 #include <utime.h>
19 #endif
20
21 #if defined(__WIN32__)
22 #define WIN32_LEAN_AND_MEAN
23 #define UNICODE
24 #include <windows.h>
25 #include <io.h>
26
27 #else
28 #include <unistd.h>
29 #endif
30
31 typedef int bool;
32 typedef unsigned char byte;
33 typedef unsigned short uint16;
34 typedef unsigned int uint;
35 typedef unsigned int FileSize;
36 typedef long long int64;
37 typedef unsigned long long uint64;
38
39 #define false 0
40 #define true 1
41
42 #define null ((void *)0)
43
44 #define MAX_LOCATION 797
45 #define MAX_FILENAME 274
46
47 void __ecereNameSpace__ecere__com__eSystem_Delete(void * memory);
48 void * __ecereNameSpace__ecere__com__eSystem_New0(unsigned int size);
49 void * __ecereNameSpace__ecere__com__eSystem_Renew(void * memory, unsigned int size);
50 void * __ecereNameSpace__ecere__com__eSystem_Renew0(void * memory, unsigned int size);
51 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16(const char * source, int * wordCount);
52 unsigned short * __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(const char * source, uint16 * dest, int max);
53 char * __ecereNameSpace__ecere__sys__UTF16toUTF8(const uint16 * source);
54 void __ecereNameSpace__ecere__sys__ChangeCh(char * string, char ch1, char ch2);
55
56 #if defined(__WIN32__) || defined(__WATCOMC__)
57 #include <direct.h>
58 __declspec(dllimport) BOOL WINAPI GetVolumePathName(LPCTSTR lpszFileName,LPTSTR lpszVolumePathName,DWORD cchBufferLength);
59 #else
60 #include <dirent.h>
61 #endif
62
63 typedef unsigned int FileAttribs;
64 typedef int64 SecSince1970;
65 typedef SecSince1970 TimeStamp;
66
67 typedef enum
68 {
69    FOM_read = 1,
70    FOM_write,
71    FOM_append,
72    FOM_readWrite,
73    FOM_writeRead,
74    FOM_appendRead
75 } FileOpenMode;
76
77 typedef enum
78 {
79    unlocked = 0,     // LOCK_UN  _SH_DENYNO
80    shared = 1,       // LOCK_SH  _SH_DENYWR
81    exclusive = 2     // LOCK_EX  _SH_DENYRW
82 } FileLock;
83
84 #define isFile       0x0001
85 #define isArchive    0x0002
86 #define isHidden     0x0004
87 #define isReadOnly   0x0008
88 #define isSystem     0x0010
89 #define isTemporary  0x0020
90 #define isDirectory  0x0040
91 #define isDrive      0x0080
92 #define isCDROM      0x0100
93 #define isRemote     0x0200
94 #define isRemovable  0x0400
95 #define isServer     0x0800
96 #define isShare      0x1000
97
98 typedef struct
99 {
100    FileAttribs attribs;
101    FileSize size;
102    SecSince1970 accessed;
103    SecSince1970 modified;
104    SecSince1970 created;
105 } FileStats;
106
107 char * __ecereNameSpace__ecere__sys__GetLastDirectory(const char * string, char * output);
108 bool __ecereNameSpace__ecere__sys__SplitArchivePath(const char * fileName, char * archiveName, char ** archiveFile);
109
110 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
111 void __ecereMethod___ecereNameSpace__ecere__sys__EARFileSystem_FixCase(const char * archive, char * name);
112
113 static BOOL CALLBACK EnumThreadWindowsProc(HWND hwnd, LPARAM lParam)
114 {
115    DWORD pid;
116    if(IsWindowVisible(hwnd) && GetWindowThreadProcessId(hwnd, &pid) && pid == GetCurrentProcessId())
117    {
118       *(void **)lParam = hwnd;
119       return FALSE;
120    }
121    return TRUE;
122 }
123 bool WinReviveNetworkResource(uint16 * _wfileName)
124 {
125    bool result = false;
126    HWND windowHandle = null;
127    NETRESOURCE nr = { 0 };
128    nr.dwType = RESOURCETYPE_DISK;
129    nr.lpRemoteName = _wfileName;
130    if(_wfileName[0] != '\\' || _wfileName[1] == '\\')
131    {
132       uint16 volumePathName[MAX_LOCATION];
133       if(GetVolumePathName(_wfileName, volumePathName, MAX_LOCATION))
134       {
135          uint16 remoteName[MAX_LOCATION];
136          DWORD size = MAX_LOCATION;
137          volumePathName[wcslen(volumePathName)-1] = 0;
138          if(WNetGetConnection(volumePathName, remoteName, &size) == ERROR_CONNECTION_UNAVAIL)
139          {
140             nr.lpRemoteName = remoteName;
141             nr.lpLocalName = volumePathName;
142          }
143          else
144             return false;
145       }
146       else
147          return false;
148    }
149    EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowsProc, (LPARAM)&windowHandle);
150    if(!windowHandle)
151    {
152       EnumWindows(EnumThreadWindowsProc, (LPARAM)&windowHandle);
153
154    }
155    if(WNetAddConnection3(windowHandle, &nr, null, null, CONNECT_INTERACTIVE|CONNECT_PROMPT) == NO_ERROR)
156       result = true;
157    return result;
158 }
159
160 TimeStamp Win32FileTimeToTimeStamp(FILETIME * fileTime);
161 void TimeStampToWin32FileTime(TimeStamp t, FILETIME * fileTime);
162
163 #endif
164
165 uint FILE_GetSize(FILE * input)
166 {
167    if(input)
168    {
169       struct stat s;
170       int fd = fileno(input);
171       if(!fstat(fd, &s))
172          return s.st_size;
173    }
174    return 0;
175 }
176
177 bool FILE_Lock(FILE * input, FILE * output, FileLock type, uint64 start, uint64 length, bool wait)
178 {
179    if(!output && !input)
180       return true;
181    else
182    {
183 #if defined(__WIN32__)
184       int handle = fileno(output ? output : input);
185       HANDLE hFile = (HANDLE)_get_osfhandle(handle);
186       OVERLAPPED overlapped = { 0 };
187       overlapped.Offset = (uint)(start & 0xFFFFFFFF);
188       overlapped.OffsetHigh = (uint)((start & 0xFFFFFFFF00000000LL) >> 32);
189       if(type ==  unlocked)
190          return UnlockFileEx(hFile, 0,
191             (uint)(length ? (length & 0xFFFFFFFF) : 0xFFFFFFFF),
192             (uint)(length ? ((length & 0xFFFFFFFF00000000LL) >> 32) : 0xFFFFFFFF),
193             &overlapped) != 0;
194       else
195          return LockFileEx(hFile, ((type == exclusive) ? LOCKFILE_EXCLUSIVE_LOCK : 0) | (wait ? 0 : LOCKFILE_FAIL_IMMEDIATELY), 0,
196             (uint)(length ? (length & 0xFFFFFFFF) : 0xFFFFFFFF),
197             (uint)(length ? ((length & 0xFFFFFFFF00000000LL) >> 32) : 0xFFFFFFFF),
198             &overlapped) != 0;
199 #else
200       struct flock fl;
201       int fd;
202
203       fl.l_type   = (type == unlocked) ? F_UNLCK : ((type == exclusive) ? F_WRLCK : F_RDLCK);
204       fl.l_whence = SEEK_SET;
205       fl.l_start  = start;
206       fl.l_len    = length;
207       fl.l_pid    = getpid();
208
209       fd = fileno(output ? output : input);
210       return fcntl(fd, wait ? F_SETLKW : F_SETLK, &fl) != -1;
211 #endif
212    }
213 }
214
215 void FILE_set_buffered(FILE * input, FILE * output, bool value)
216 {
217 #if !defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
218    if(input)
219       setvbuf(input, null, value ? _IOFBF : _IONBF, 0);
220    if(output && output != input)
221       setvbuf(output, null, value ? _IOFBF : _IONBF, 0);
222 #endif
223 }
224
225 FileAttribs FILE_FileExists(const char * fileName)
226 {
227 #ifdef __WIN32__
228    FileAttribs result = 0;
229    uint attribute = 0;  // Initialization isn't actually required here but GCC complains about it.
230    uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
231    if(!strcmp(fileName, "/") || !strcmp(fileName, "\\\\"))
232    {
233       result = (FileAttribs)(isDirectory);
234    }
235    else
236       attribute = GetFileAttributes(_wfileName);
237 #if !defined(ECERE_BOOTSTRAP)
238    if(!result && attribute == 0xFFFFFFFF)
239    {
240       if(WinReviveNetworkResource(_wfileName))
241          attribute = GetFileAttributes(_wfileName);
242       if(attribute == 0xFFFFFFFF)
243       {
244          if(fileName[0] == '\\' && fileName[1] == '\\')
245          {
246             NETRESOURCE nr = { 0 };
247             NETRESOURCE * buffer = null;
248             unsigned int size = sizeof(NETRESOURCE);
249             uint16 * dir;
250
251             nr.dwScope       = RESOURCE_GLOBALNET;
252             nr.dwType        = RESOURCETYPE_DISK;
253             nr.lpRemoteName  = _wfileName;
254             nr.lpProvider = L"Microsoft Windows Network";
255
256             buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_New0(size);
257             while(true)
258             {
259                int returnCode = WNetGetResourceInformationW(&nr, buffer, (DWORD *)&size, &dir);
260                if(returnCode == WN_MORE_DATA)
261                   buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_Renew0(buffer, size);
262                else
263                {
264                   if(returnCode == WN_SUCCESS)
265                   {
266                      if(!_wcsicmp(buffer->lpRemoteName, _wfileName))
267                         result = (FileAttribs)( isDirectory | isServer );
268                   }
269                   break;
270                }
271             }
272             __ecereNameSpace__ecere__com__eSystem_Delete(buffer);
273          }
274       }
275    }
276 #endif
277    if(!result && attribute != 0xFFFFFFFF)
278    {
279       if(attribute & FILE_ATTRIBUTE_DIRECTORY)
280          result = (FileAttribs)( isDirectory );
281       else
282          result = (FileAttribs)(isFile);
283    }
284    __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
285    return result;
286 #else
287    if(!access(fileName, F_OK))
288    {
289       struct stat s;
290       stat(fileName, &s);
291       return S_ISDIR(s.st_mode) ? (FileAttribs) ( isDirectory ) : (FileAttribs) ( isFile );
292    }
293    else
294    {
295       // TODO: Check this
296       return (FileAttribs) 0;
297    }
298 #endif
299 }
300
301 bool FILE_FileGetSize(const char * fileName, FileSize * size)
302 {
303    bool result = false;
304 #if defined(__WIN32__)
305    struct _stat s;
306    uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
307    if(!_wstat(_wfileName, &s))
308 #else
309    struct stat s;
310    if(!stat(fileName, &s))
311 #endif
312    {
313       *size = s.st_size;
314       result = true;
315    }
316 #if defined(__WIN32__)
317    __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
318 #endif
319    return result;
320 }
321
322 bool FILE_FileGetStats(const char * fileName, FileStats * stats)
323 {
324    bool result = false;
325 #if defined(__WIN32__)
326    uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
327    struct _stat s;
328    if(!_wstat(_wfileName, &s))
329 #else
330    struct stat s;
331    if(!stat(fileName, &s))
332 #endif
333    {
334       stats->size = s.st_size;
335       stats->attribs = (s.st_mode & S_IFDIR) ? ((FileAttribs) (isDirectory)): ((FileAttribs) 0);
336
337 #if defined(__WIN32__)
338       {
339          HANDLE hFile = CreateFile(_wfileName, 0, FILE_SHARE_READ, null,
340             OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, null);
341          if(hFile != INVALID_HANDLE_VALUE)
342          {
343 #if defined(ECERE_BOOTSTRAP)
344             stats->created  = 0;
345             stats->accessed = 0;
346             stats->modified = 0;
347 #else
348             FILETIME c, a, m;
349             GetFileTime(hFile, &c, &a, &m);
350             stats->created  = Win32FileTimeToTimeStamp(&c);
351             stats->accessed = Win32FileTimeToTimeStamp(&a);
352             stats->modified = Win32FileTimeToTimeStamp(&m);
353 #endif
354
355             CloseHandle(hFile);
356          }
357       }
358 #else
359       stats->accessed = s.st_atime;
360       stats->created = s.st_ctime;
361       stats->modified = s.st_mtime;
362 #endif
363 /*
364       stats->attribs.isArchive   = (winFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)   ? true : false;
365       stats->attribs.isHidden    = (winFile.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)    ? true : false;
366       stats->attribs.isReadOnly  = (winFile.dwFileAttributes & FILE_ATTRIBUTE_READONLY)  ? true : false;
367       stats->attribs.isSystem    = (winFile.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)    ? true : false;
368       stats->attribs.isTemporary = (winFile.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? true : false;
369       stats->attribs.isDirectory = (winFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false;
370 */
371       result = true;
372    }
373 #if defined(__WIN32__)
374    __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
375 #endif
376    return result;
377 }
378
379 void FILE_FileFixCase(char * file)
380 {
381 #if defined(__WIN32__)
382 #ifndef ECERE_BOOTSTRAP
383    char archive[MAX_LOCATION], * name;
384    if(__ecereNameSpace__ecere__sys__SplitArchivePath(file, archive, &name))
385    {
386       char fileName[MAX_LOCATION];
387       strcpy(fileName, name);
388       __ecereMethod___ecereNameSpace__ecere__sys__EARFileSystem_FixCase(archive, fileName);
389       if(archive[0] != ':')
390          FILE_FileFixCase(archive);
391       sprintf(file, "<%s>%s", archive, fileName);
392    }
393    else
394 #endif
395    {
396       int c = 0;
397       char parent[MAX_LOCATION] = "";
398
399       // Skip network protocols
400       if(strstr(file, "http://") == file) return;
401
402       // Copy drive letter to new path
403       if(file[0] && file[1] == ':')
404       {
405          parent[0] = (char)toupper(file[0]);
406          parent[1] = ':';
407          parent[2] = '\0';
408          c = 2;
409       }
410       // Copy Microsoft Network string to new path
411       else if(file[0] == '\\' && file[1] == '\\')
412       {
413          parent[0] = parent[1] = '\\';
414          parent[2] = '\0';
415          c = 2;
416       }
417       else if(file[0] == '/' && file[1] == '/')
418       {
419          parent[0] = parent[1] = '\\';
420          parent[2] = '\0';
421          c = 2;
422       }
423       // Copy Entire Computer to new path
424       else if(file[0] == '/'  && !file[1])
425
426       {
427          parent[0] = '/';
428          parent[1] = '\0';
429          c = 1;
430       }
431
432       while(file[c])
433       {
434          // Get next directory
435          char directory[MAX_FILENAME];
436          int len = 0;
437          char ch;
438          for(;(ch = file[c]) && (ch == '/' || ch == '\\'); c++);
439          for(;(ch = file[c]) && (ch != '/' && ch != '\\'); c++)
440          {
441             if(len < MAX_FILENAME)
442                directory[len++] = ch;
443          }
444          directory[len] = '\0';
445
446          // Normal file
447          if(parent[0] != '\\' || parent[1] != '\\' || strstr(parent+2, "\\"))
448          {
449             if(strcmp(directory, "..") && strcmp(directory, "."))
450             {
451                WIN32_FIND_DATA winFile;
452                uint16 dir[MAX_PATH];
453                HANDLE handle;
454
455                __ecereNameSpace__ecere__sys__UTF8toUTF16Buffer(parent, dir, MAX_PATH);
456                if(dir[0]) wcscat(dir, L"\\");
457                {
458                   uint16 * _wdirectory = __ecereNameSpace__ecere__sys__UTF8toUTF16(directory, null);
459                   wcscat(dir, _wdirectory);
460                   __ecereNameSpace__ecere__com__eSystem_Delete(_wdirectory);
461                }
462
463                handle = FindFirstFile(dir, &winFile);
464                if(parent[0] || (file[0] == '\\' || file[0] == '/'))
465                   strcat(parent, "\\");
466                if(handle != INVALID_HANDLE_VALUE)
467                {
468                   char * utf8 = __ecereNameSpace__ecere__sys__UTF16toUTF8(winFile.cFileName);
469                   strcat(parent, utf8);
470                   __ecereNameSpace__ecere__com__eSystem_Delete(utf8);
471                   FindClose(handle);
472                }
473                else
474                   strcat(parent, directory);
475             }
476             else
477             {
478                if(parent[0] || (file[0] == '\\' || file[0] == '/'))
479                   strcat(parent, "\\");
480
481                strcat(parent, directory);
482             }
483          }
484 #ifndef ECERE_BOOTSTRAP
485          else
486          {
487             // Network server
488             if(parent[2])
489             {
490                HANDLE handle = 0;
491                DWORD count = 0xFFFFFFFF;
492                DWORD size = 512 * sizeof(NETRESOURCE);
493                NETRESOURCE * buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_New0(size);
494                NETRESOURCE nr = {0};
495                int c;
496
497                nr.dwScope = RESOURCE_GLOBALNET;
498                nr.dwType = RESOURCETYPE_DISK;
499                // UNICODE FIX
500                nr.lpRemoteName = __ecereNameSpace__ecere__sys__UTF8toUTF16(parent, null);
501                nr.lpProvider = L"Microsoft Windows Network";
502
503                // Server
504                WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK, 0, &nr, &handle);
505                if(handle)
506                {
507                   while(true)
508                   {
509                      int returnCode = WNetEnumResource(handle, &count, buffer, &size);
510                      if(returnCode != ERROR_MORE_DATA)
511                         break;
512                      count = 0xFFFFFFFF;
513                      buffer = (NETRESOURCE *)__ecereNameSpace__ecere__com__eSystem_Renew0(buffer, size);
514                   }
515                   WNetCloseEnum(handle);
516                }
517                else
518                   count = 0;
519
520                for(c = 0; c<count; c++)
521                {
522                   char shareName[MAX_FILENAME];
523                   char * remoteName = __ecereNameSpace__ecere__sys__UTF16toUTF8(buffer[c].lpRemoteName);
524                   __ecereNameSpace__ecere__sys__GetLastDirectory(remoteName, shareName);
525                   __ecereNameSpace__ecere__com__eSystem_Delete(remoteName);
526                   if(!strcmpi(directory, shareName))
527                   {
528                      strcpy(directory, shareName);
529                      break;
530                   }
531                }
532                if(c == count)
533                   strlwr(directory);
534
535                __ecereNameSpace__ecere__com__eSystem_Delete(nr.lpRemoteName);
536                __ecereNameSpace__ecere__com__eSystem_Delete(buffer);
537
538                strcat(parent, "\\");
539                strcat(parent, directory);
540             }
541             // Network share
542             else
543             {
544                strlwr(directory);
545                directory[0] = (char)toupper(directory[0]);
546                strcat(parent, directory);
547             }
548          }
549 #endif
550       }
551       strcpy(file, parent);
552    }
553 #else
554    __ecereNameSpace__ecere__sys__ChangeCh(file, '\\', '/');
555 #endif
556 }
557
558 void FILE_FileOpen(const char * fileName, FileOpenMode mode, FILE ** input, FILE **output)
559 {
560 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
561    uint16 * _wfileName = __ecereNameSpace__ecere__sys__UTF8toUTF16(fileName, null);
562    /*
563    file.handle = CreateFile(_wfileName,
564       ((mode == FOM_read || mode == FOM_readWrite || mode == FOM_writeRead || mode == FOM_appendRead) ? GENERIC_READ : 0) |
565       ((mode == FOM_write || mode == FOM_append || mode == FOM_readWrite || mode == FOM_writeRead || mode == FOM_appendRead) ? GENERIC_WRITE: 0),
566       FILE_SHARE_READ|FILE_SHARE_WRITE,
567       null,
568       (mode == write || mode == writeRead) ? TRUNCATE_EXISTING : ((mode == read || mode == readWrite) ? OPEN_EXISTING : OPEN_ALWAYS), 0, null);
569    if(file.handle)
570    {
571       int flags;
572       int handle;
573       switch(mode)
574       {
575          case FOM_read:       handle = _open_osfhandle((int)file.handle, _O_RDONLY); break;
576          case FOM_write:      handle = _open_osfhandle((int)file.handle, _O_WRONLY | _O_CREAT | _O_TRUNC); break;
577          case FOM_append:     handle = _open_osfhandle((int)file.handle, _O_WRONLY | _O_CREAT | _O_APPEND); break;
578          case FOM_readWrite:  handle = _open_osfhandle((int)file.handle, _O_RDWR); break;
579          case FOM_writeRead:  handle = _open_osfhandle((int)file.handle, _O_RDWR | _O_CREAT | _O_TRUNC); break;
580          case FOM_appendRead: handle = _open_osfhandle((int)file.handle, _O_RDWR | _O_APPEND | _O_CREAT); break;
581       }
582       if(handle)
583       {
584          switch(mode)
585          {
586             case FOM_read:       *input = _fdopen(handle, "rb"); break;
587             case FOM_write:      *output = _fdopen(handle, "wb"); break;
588             case FOM_append:     *output = _fdopen(handle, "ab"); break;
589             case FOM_readWrite:  *input = *output = _fdopen(handle, "r+b"); break;
590             case FOM_writeRead:  *input = *output = _fdopen(handle, "w+b"); break;
591             case FOM_appendRead: *input = *output = _fdopen(handle, "a+b"); break;
592          }
593       }
594    }
595    */
596    switch(mode)
597    {
598       case FOM_read:       *input = _wfopen(_wfileName, L"rb"); break;
599       case FOM_write:      *output = _wfopen(_wfileName, L"wb"); break;
600       case FOM_append:     *output = _wfopen(_wfileName, L"ab"); break;
601       case FOM_readWrite:  *input = *output = _wfopen(_wfileName, L"r+b"); break;
602       case FOM_writeRead:  *input = *output = _wfopen(_wfileName, L"w+b"); break;
603       case FOM_appendRead: *input = *output = _wfopen(_wfileName, L"a+b"); break;
604    }
605    if(!mode && WinReviveNetworkResource(_wfileName))
606    {
607       switch(mode)
608       {
609          case FOM_read:       *input = _wfopen(_wfileName, L"rb"); break;
610          case FOM_write:      *output = _wfopen(_wfileName, L"wb"); break;
611          case FOM_append:     *output = _wfopen(_wfileName, L"ab"); break;
612          case FOM_readWrite:  *input = *output = _wfopen(_wfileName, L"r+b"); break;
613          case FOM_writeRead:  *input = *output = _wfopen(_wfileName, L"w+b"); break;
614          case FOM_appendRead: *input = *output = _wfopen(_wfileName, L"a+b"); break;
615       }
616    }
617    __ecereNameSpace__ecere__com__eSystem_Delete(_wfileName);
618 #else
619    switch(mode)
620    {
621       case FOM_read:       *input = fopen(fileName, "rb"); break;
622       case FOM_write:      *output = fopen(fileName, "wb"); break;
623       case FOM_append:     *output = fopen(fileName, "ab"); break;
624       case FOM_readWrite:  *input = *output = fopen(fileName, "r+b"); break;
625       case FOM_writeRead:  *input = *output = fopen(fileName, "w+b"); break;
626       case FOM_appendRead: *input = *output = fopen(fileName, "a+b"); break;
627    }
628 #endif
629 }